平台 Debian 9 | 手臂
我有一个用于在 a 上存储线程 ID 的类,std::list
然后将列表打印为关闭过程的一部分。有两种静态方法:AddId()
和PrintIds()
。由于静态方法由多个线程使用,因此列表访问受到保护std::mutex
。我遇到了两个让我感到困惑的问题,它们可能是相关的。我希望你们中的一个可以帮助解释我所缺少的。
注意我首先使用了 scoped s,并且出于此处解释的原因std::lock_guard<std::mutex>
暂时选择了代码中显示的 s。std::unique_lock<std::mutex>
问题 1 程序启动时,所有线程都会调用ThreadMgr::AddId()
,这会将线程 ID 和字符串名称一起添加到列表中。这似乎工作正常。但是,ThreadMgr::PrintIds()
在关闭过程中调用时,std::mutex
仍然被锁定并std::lock_guard
阻塞。在测试时,我解锁了std::mutex
前面的行中的- 如果它没有被调用线程锁定,这std::lock_guard
是未定义的行为- 然后它按预期工作。唯一std::mutex
使用的地方是在这两个方法中,并且在std::lock_guard
作用域中,std::mutex
应该在每次方法调用时解锁。我经历了几次std::mutex
直接锁定和解锁的迭代,使用std::unique_lock
std::unique_lock
s 等。我最终使用此处提供的代码中的 s 找到了一个可行的解决方案。然而,这也让我感到困惑。
std::unique_lock
如果我使用 s 工作,std::adopt_lock
但仅限于ThreadMgr::PrintIds()
. 如果我使用std::adopt_lock
in ThreadMgr::AddId()
,那么无论何时ThreadMgr::PrintIds()
调用都会出现分段错误。
问题 2如前所述,当所有线程在启动时调用它时ThreadMgr::AddId()
运行良好。但是,在某些 UI 会话中,每个会话都会产生一个线程。当从这些会话线程之一调用时,两者和块都已经锁定。因此,对于其他所有线程都可以正常工作,但不适用于稍后启动的会话线程。std::lock_guard
std::unique_lock
ThreadMgr::AddId()
std::lock_guard
std::unique_lock
std::mutex
ThreadMgr::AddId()
如果我可以提供任何其他信息来帮助找到解决方案,请告诉我。
class ThreadMgr {
public:
ThreadMgr();
~ThreadMgr();
static void AddId(std::string);
static void PrintIds();
private:
static std::list<ThreadId> t_list;
static std::mutex list_mtx;
};
/*Definition*/
ThreadMgr::ThreadMgr() {}
ThreadMgr::~ThreadMgr() {}
/*Static Members*/
void ThreadMgr::AddId(std::string name) {
ThreadId t_id = getThreadId(name);
{
std::unique_lock<std::mutex> lock(list_mtx);
t_list.push_front(t_id);
}
std::lock_guard<std::mutex> lk(cout_mtx);
std::cout << "---Added id: " << t_id.tid << " for the " << name << " thread." << std::endl;
return;
}
void ThreadMgr::PrintIds() {
std::ostringstream oss;
oss << "\n**************************Thread Ids**************************\n";
{
std::unique_lock<std::mutex> lock(list_mtx, std::adopt_lock);
for (std::list<ThreadId>::iterator t = t_list.begin(); t != t_list.end(); t++) {
oss << "---" << t->name << " : " << t->tid << '\n';
}
}
oss << "************************End Thread Ids************************" << '\n';
std::lock_guard<std::mutex> lk(cout_mtx);
std::cout << oss.str() << std::endl;
return;
}
std::mutex ThreadMgr::list_mtx;
std::list<ThreadId> ThreadMgr::t_list;
int Main(){
ThreadMgr::AddId("Main");
std::thread MbServerT(MbServer);
std::thread UiServerT(UiServer);
while(run){
//do stuff
}
ThreadMgr::PrintIds();
if(MbServerT.joinable())
MbServerT.join();
if(UiServerT.joinable())
UiServerT.join();
return 0;
}