0

平台 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_lockstd::unique_locks 等。我最终使用此处提供的代码中的 s 找到了一个可行的解决方案。然而,这也让我感到困惑。

std::unique_lock如果我使用 s 工作,std::adopt_lock但仅限于ThreadMgr::PrintIds(). 如果我使用std::adopt_lockin ThreadMgr::AddId(),那么无论何时ThreadMgr::PrintIds()调用都会出现分段错误。

问题 2如前所述,当所有线程在启动时调用它时ThreadMgr::AddId()运行良好。但是,在某些 UI 会话中,每个会话都会产生一个线程。当从这些会话线程之一调用时,两者和块都已经锁定。因此,对于其他所有线程都可以正常工作,但不适用于稍后启动的会话线程。std::lock_guardstd::unique_lockThreadMgr::AddId()std::lock_guardstd::unique_lockstd::mutexThreadMgr::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;
}
4

0 回答 0