我有一个关于notify_one函数的问题。在下面的代码中,
#include <iostream>
#include <condition_variable>
#include <thread>
#include <chrono>
#include <mutex>
std::condition_variable cv;
std::mutex m;
bool ready = false;
void f()
{
std::unique_lock<std::mutex> lk(m);
std::cout << "get into wait, ready=" << ready << std::endl;
cv.wait(lk, []() { return ready; });
std::cout << "get out of wait, ready=" << ready << std::endl;
}
int main()
{
std::thread a(f);
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::unique_lock<std::mutex> lk(m, std::defer_lock);
if (lk.try_lock()) {
std::cout << "main try_lock success, ready=" << ready << std::endl;
ready = true;
}
}
std::cout << "main notify, ready=" << ready << std::endl;
cv.notify_one();
// std::cout << "hello" << std::endl;
{
std::unique_lock<std::mutex> lk(m, std::defer_lock);
if (lk.try_lock()) {
std::cout << "main try_lock success, ready=" << ready << std::endl;
ready = true;
}
}
std::cout << "main notify, ready=" << ready << std::endl;
cv.notify_one();
a.join();
return 0;
}
我得到以下结果,
get into wait, ready=0
main try_lock success, ready=0
main notify, ready=1
main try_lock success, ready=1
main notify, ready=1
get out of wait, ready=1
但我预计结果如下,因为根据 page ,如果调用notify_one,则wait被解除阻塞,并重新获取mutex(m)的锁。
get into wait, ready=0
main try_lock success, ready=0
main notify, ready=1
main notify, ready=1
get out of wait, ready=1
我发现如果我注释掉std::cout << "hello" << std::endl;
我得到了预期的结果。在我看来,notify_one 不会立即解除等待。这是正确的吗?
非常感谢!
最佳答案
Looks to me like notify_one does not immediately unblock the wait. It is correct?
通知立即解除阻塞等待,这意味着等待能够在通知后恢复。也就是说,休眠线程被标记为可运行。
但是,调度程序不一定立即重新启动它。如果它必须抢占一些已经运行的线程/进程,它可能会等到yield、系统调用或其他取消点,否则甚至不会查看新运行的线程,直到当前时间片结束。
解除阻塞与强制立即上下文切换不同(这是幸运的,否则同步的成本会更高)。
关于c++ - condition_variable::notify_one 不会立即解除等待?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64891918/