多等待使用通知全部
我希望等待使用条件变量。多等待使用通知全部
我已经创建了一个包含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();
}
这不是条件变量的工作方式。
要认识到的主要问题是条件变量不能可靠地单独发出事件信号。特别是,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
轻松地实现自己的屏障。
回复,“通知已不等待等待......”的另一种说法是,'cv.notify()'和'cv.notify_all()'在ALL_不做_anything除非有其他线程已经在等待一个'cv.wait()'调用。 –
除非您有什么需要等待的地方,否则不能调用wait。你不能调用'notify_all',除非你有通知的线程。而且,最糟糕的是,你的互斥锁并不能保护任何东西!它应该是保护你正在等待的东西以及你正在通知的东西! –