考虑第一个线程函数和全局变量:
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()队列?否则,显然通知没有发送。
没有队列。如果一个线程调用notify_one
并且没有其他线程在等待它不会执行任何操作。
这就是为什么你有谓词,在你的例子中
officer.wait(lock,[this](){ return secondPlayerIsReady;});
所以当一个线程调用它时,如果secondPlayerIsReady
是 true,那么线程根本不会等待,而是跳过这一行。
所以打电话notify_one
只要标志设置正确,太“早”就不是问题。请记住,修改标志时需要受到互斥锁的保护。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)