C++ 使用notify all进行多次等待

C++ 使用notify all进行多次等待,c++,multithreading,c++14,C++,Multithreading,C++14,我希望使用带有wait的条件变量 我创建了一个有10个线程的程序,每个线程都等待来自主线程的信号notify_all()。但它陷入了僵局,我不想理解为什么 #include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex, std::unique_lock #inc

我希望使用带有wait的条件变量

我创建了一个有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();
}
#包括//std::cout
#include//std::thread
#包括//std::mutex、std::unique\u lock
#include//std::condition\u变量
#包括
使用名称空间std;
std::互斥mtx;
std::条件变量cv;
int xx=0;
无效打印id(内部id){
标准:唯一锁定lck(mtx);

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

需要了解的主要问题是,条件变量本身无法可靠地向事件发送信号。特别是,
wait()
调用可能会错误返回,也就是说,没有人调用
notify

相反,您需要的是与条件变量关联的周围程序中的一个逻辑条件。只要条件发生变化,就调用notify,并让
wait
检查条件

另一个需要注意的问题是,虽然等待无法在不发生通知的情况下继续(逻辑上,假设没有虚假唤醒),但情况并非如此
函数可能在
print\u id
函数到达第一次等待之前运行到完成。该等待将被永久阻止,因为途中没有更多通知。通知不等待等待,它们是触发和忘记操作

在正确使用条件变量时,这不是一个问题,因为等待只是等待逻辑条件发生更改。如果在等待调用之前已经发生了更改,则您会检测到它,并且不会首先调用wait


这里您可能想要的是a的行为。您可以使用
int
计数器作为条件,使用
condition\u变量
mutex
进行同步,轻松实现您自己的屏障。

除非您有事情要等待,否则您不能调用
wait
。并且您不能调用
notify\u all
除非你有什么东西要通知线程。最糟糕的是,你的互斥锁没有保护任何东西!它应该保护你正在等待的东西和你正在通知的东西!re,“通知不要等待等待…”另一种说法是,
cv.notify()
cv.notify\u all()
除非其他线程已经在
cv.wait()调用中等待,否则不要执行任何操作。