使用notify all进行多次等待

时间:2017-08-28 08:39:25

标签: c++ multithreading c++14

我希望使用条件变量和等待。

我创建了一个包含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();
}

1 个答案:

答案 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计数器作为条件轻松实现自己的障碍,并使用mutexecho "text" > a.txt进行同步。