考虑第一线程函数和全局变量:
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;});
}
}
它调用一些环和环()返回一个继续条件;然后,它更新准备值下一个循环的每个线程;
考虑下一个线程:
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秒,然后等待(),直到第一个线程被锁定后调用notify_one();此外,类似于第一个线程。
先验,与#1标签线路被先前执行比用#2标签的线,因此,通知已早先发送比所述第二线程被锁定。现在的问题是 - 是否有notify_one()队列?否则,该通知未发送,效果显着。
没有队列。如果一个线程调用notify_one
并且没有其他线程等待它不会做任何事情。
这就是为什么你有谓语,在你的榜样
officer.wait(lock,[this](){ return secondPlayerIsReady;});
一个线程调用此所以的时候,如果secondPlayerIsReady
是真实的,那么该线程将不会等待,只是跳过这一行。
因此调用notify_one
过“早”是没有问题的,只要标志设置正确。只要记住该标志需要修改时,必须由互斥保护。