多等待使用通知全部

问题描述:

我希望等待使用条件变量。多等待使用通知全部

我已经创建了一个包含10个线程的程序,每个线程都在主线程中等待信号notify_all()。但它陷入僵局,我不想理解为什么。

#include <iostream>   // std::cout 
#include <thread>    // std::thread 
#include <mutex>    // std::mutex, std::unique_lock 
#include <condition_variable> // std::condition_variable 
#include <chrono> 

using namespace std; 

std::mutex mtx; 
std::condition_variable cv; 
int xx = 0; 

void print_id (int id) { 
    std::unique_lock<std::mutex> lck(mtx); 
    cout<<"Start thread id " << id << " \n"; 

    for(int i=0; i<9; i++) 
    { 
     cout<<"Thread " << id << " i " << i <<"\n"; 
     cv.wait(lck); 
    } 
} 

void go() 
{ 
    cv.notify_all(); 
    for(int i=0; i<10; i++) 
    { 
     //Some works for threads 
     cv.notify_all(); 
    } 
} 

int main() 
{ 
    std::thread threads[10]; 
    for (int i=0; i<10; ++i) 
     threads[i] = std::thread(print_id,i); 

    std::cout << "10 threads ready to race...\n"; 
    go();      // go! 

    for (auto& th : threads) th.join(); 
} 
+2

除非您有什么需要等待的地方,否则不能调用wait。你不能调用'notify_all',除非你有通知的线程。而且,最糟糕的是,你的互斥锁并不能保护任何东西!它应该是保护你正在等待的东西以及你正在通知的东西! –

这不是条件变量的工作方式。

要认识到的主要问题是条件变量不能可靠地单独发出事件信号。特别是,wait()调用可能会虚假地返回,也就是说,没有任何人调用notify

相反,你需要的是逻辑条件在你的周边程序中,条件变量是绑定的。只要条件发生变化,您就会通知通知,并且wait检查条件,either as part of a surrounding loop or inside the wait by providing a checker predicate function as an argument to the call

另一个问题需要注意的是,虽然等待不能继续没有通知存在的(在逻辑上,假设没有杂散唤醒),相反的是不正确的。也就是说,即使在print_id函数已经达到第一次等待之前,go()函数也可能会运行完成。那样的等待将永远被阻止,因为在途中没有更多的通知。通知不会等待等待,它们是“即燃即用”操作。

在正确使用的条件变量,这不是一个问题,因为等待只是等待的逻辑条件改变。如果在等待呼叫之前已经发生了这种变化,那么您会发现它,并且不要在第一时间呼叫等待。

什么你可能想在这里是一个barrier的行为。您可以使用int计数器的条件和condition_variable和同步mutex轻松地实现自己的屏障。

+0

回复,“通知已不等待等待......”的另一种说法是,'cv.notify()'和'cv.notify_all()'在ALL_不做_anything除非有其他线程已经在等待一个'cv.wait()'调用。 –