使用std::互斥对象的数组时,Conditional_variable不会触发

conditional_variable does not trigger when using array of std::mutex

本文关键字:variable Conditional std 对象 数组 使用      更新时间:2023-10-16

此应用程序是递归多线程分离的应用程序。每个线程重新生成在它死之前有一堆新的线程。选项1(可以),但是它是共享资源,因此会减慢应用程序的速度。选项2应该可以消除这个瓶颈。

选项1有效:

std::condition_variable cv;
bool ready = false;
std::mutex mu;
// go triggers the thread's function
void go() {
    std::unique_lock<std::mutex> lck( mu );
    ready = true;
    cv.notify_all();
}
void ThreadFunc ( ...) {
    std::unique_lock<std::mutex> lck ( mu );
    cv.wait(lck, []{return ready;});
    do something useful
}

选项2不触发线程:

std::array<std::mutex, DUToutputs*MaxGnodes> arrMutex ;
void go ( long m , long Channel )
{
    std::unique_lock<std::mutex> lck( arrMutex[m+MaxGnodes*Channel] );
    ready = true;
    cv.notify_all();
}

void ThreadFunc ( ...) {
    std::unique_lock<std::mutex> lck ( arrMutex[Inst+MaxGnodes*Channel] );
    while (!ready) cv.wait(lck);
    do something useful
}

我如何使选项#2工作?

选项2中的代码在变量ready上包含所谓的数据竞争,因为对该变量的读写操作不再同步。具有数据竞争的程序的行为是未定义的。您可以通过将bool ready更改为std::atomic<bool> ready来删除数据竞争

这应该已经解决了选项2中的问题。但是,如果使用std::atomic,还可以进行其他优化:
std::atomic<bool> ready{false};
void go(long m, long Channel) {
    // no lock required
    ready = true;
    cv.notify_all();
}
void ThreadFunc( ...) {
    std::unique_lock<std::mutex> lck(arrMutex[Inst+MaxGnodes*Channel]);
    cv.wait(lck, [] { return ready; });
    // do something useful
}