是否有notify_one()队列?

时间:2019-02-04 09:47:19

标签: c++ multithreading race-condition

考虑第一个线程函数和全局变量:

    std::mutex mut;
    std::condition_variable officer;
    bool firstPlayerIsReady = false;
    bool secondPlayerIsReady = false;

void firstPlayer(){
    constexpr auto doIt = true;
    while(doIt)
    {
        std::unique_lock lock{mut};
        auto toContinue = ring();
        secondPlayerIsReady = true;
        firstPlayerIsReady = false;
        officer.notify_one();   //#1
        if(!toContinue) return;
        officer.wait(lock,[=](){ return firstPlayerIsReady;});
    }
}

它调用了一些ring,ring()返回一个连续条件; 然后,它在下一个循环中为每个线程更新就绪值;

考虑下一个线程:

void secondPlayer(){
    constexpr auto doIt = true;
    while(doIt)
    {
        auto period = std::chrono::seconds(5);
        std::this_thread::sleep_for(period);

        std::unique_lock lock{mut};   //#2
        officer.wait(lock,[this](){ return secondPlayerIsReady;});
        auto toContinue = ring();
        firstPlayerIsReady = true;
        secondPlayerIsReady = false;
        officer.notify_one();
        if(!toContinue) return;
    }
}

该线程等待5秒钟,之后被wait()锁定,直到第一个线程调用notify_one(); 此外,类似于第一个线程。

先验地,带有#1标记的行比带有#2标记的行更早执行,因此通知是在第二个线程被锁定之前发送的。 问题是-是否有notify_one()队列?否则,显然不会发送通知。

1 个答案:

答案 0 :(得分:5)

没有队列。如果一个线程调用notify_one,并且没有其他线程在等待,它将不会执行任何操作。

这就是为什么在您的示例中有谓词的原因

officer.wait(lock,[this](){ return secondPlayerIsReady;});

因此,当线程调用此函数时,如果secondPlayerIsReady为true,则该线程根本不会等待,而只是跳过这一行。

因此,只要正确设置了标志,就可以太早地调用notify_one并不是问题。只需记住,修改后该标志需要由互斥体保护。