并非所有线程都通知condition_variable.notify_all()

时间:2016-07-04 12:15:11

标签: c++ multithreading condition-variable

我有以下情况:

condition_variable cv;
mutex mut;

// Thread 1:
void run() {
    while (true) {
        mut.lock();
        // create_some_data();
        mut.unlock();
        cv.notify_all();        
    }
}

// Thread 2
void thread2() {
    mutex lockMutex;
    unique_lock<mutex> lock(lockMutex);
    while (running) {
        cv.wait(lock);
        mut.lock();
        // copy data
        mut.unlock();
        // process data
    }
}

// Thread 3, 4... - same as Thread 2

我一直运行线程1来获取新数据。其他线程等待condition_variable,直到有新数据可用,然后复制它并对其进行一些处理。由线程执行的工作在完成所需的时间上有所不同,这个想法是线程只有在完成旧数据时才会获得新数据。同时获得的数据被允许被错过&#34;。我不使用共享互斥锁(仅用于访问数据),因为我不希望线程相互依赖。

上面的代码在Windows上工作正常,但是现在我在Ubuntu上运行它,我注意到在调用notify_all()时只有一个线程被通知而其他线程只在wait()上挂起。 这是为什么? Linux是否需要使用不同的方法来使用condition_variable?

3 个答案:

答案 0 :(得分:2)

幸运的是。

互斥锁和条件变量是同一构造的两个部分。你不能混用和匹配互斥锁和cvs。

试试这个:

void thread2() {
    unique_lock<mutex> lock(mut); // use the global mutex
    while (running) {
        cv.wait(lock);
        // mutex is already locked here
        // test condition. wakeups can be spurious
        // copy data
        lock.unlock();
        // process data

        lock.lock();
    }
}

答案 1 :(得分:2)

您的代码会立即显示UB,因为它会重新锁定cv在退出等待时重新锁定的唯一锁定。

还有其他问题,例如没有检测到虚假的唤醒。

最后cv通知所有onky通知当前正在等待的线程。如果线程稍后出现,则没有骰子。

答案 2 :(得分:1)

this documentation

  

任何打算在std :: condition_variable上等待的线程都必须

     
      
  1. 在与以前相同的互斥锁上获取std :: unique_lock,   保护共享变量
  2.   
  3. 执行wait,wait_for或wait_until。等待操作以原子方式释放互斥锁并暂停执行   线程。
  4.   
  5. 当通知条件变量时,超时到期,或者发生虚假唤醒,线程被唤醒,互斥锁是   原子地重新获得。然后线程应该检查条件   如果醒来是假的,可以继续等待。
  6.   

此代码

void thread2() {
    mutex lockMutex;
    unique_lock<mutex> lock(lockMutex);
    while (running) {

没有那样做。