我希望使用条件变量和等待。
我创建了一个包含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();
}
答案 0 :(得分:3)
这不是条件变量的工作原理。
要实现的主要事情是条件变量无法可靠地自行发出事件信号。特别是notify
次调用可能会虚假地返回,也就是说,没有人调用wait
。
而你需要的是你的周围程序中的逻辑条件,条件变量与之相关。只要条件发生变化并go()
检查条件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
函数到达第一个等待之前,int
函数也可能会运行完成。那个等待将永远被阻止,因为在途中没有更多的通知。通知不等待等待,它们是即发即弃的操作。
正确使用条件变量这不是问题,因为等待只是等待逻辑条件改变。如果在等待呼叫之前已经发生了这种变化,则会检测到它并且不会在第一时间调用等待。
你可能想要的是barrier的行为。您可以使用condition_variable
计数器作为条件轻松实现自己的障碍,并使用mutex
和echo "text" > a.txt
进行同步。