![](/img/trans.png)
[英]std::condition_variable wait() and notify_one() synchronization
[英]condition_variable::notify_one does not instantly unblock wait?
我有一個關於 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 ,則等待解鎖並重新獲取 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 不會立即解除等待。 它是正確的?
非常感謝!
在我看來,notify_one 不會立即解除等待。 它是正確的?
通知立即解除等待,這意味着等待能夠在通知后恢復。 也就是說,休眠線程被標記為可運行。
但是,調度程序不一定會立即重新啟動它。 如果它必須搶占一些已經運行的線程/進程,它可能會等待直到產生、系統調用或其他一些取消點,否則在當前時間片結束之前甚至不會查看新運行的線程。
解除阻塞與強制立即進行上下文切換不同(這是幸運的,否則同步會更加昂貴)。
在你的第一個cv.notify_one();
您沒有同步點(直到a.join();
)並且已經運行的線程很可能會繼續運行並到達a.join();
在調度程序決定讓另一個線程旋轉之前。
作為實驗,您可以通過在通知后稍作休眠來讓出線程的執行槽——這可能會導致輸出的順序與您預期的一樣。
cv.notify_one();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
但是不要在生產代碼中依賴它。 這不能保證任何事情,因為線程之間沒有同步(除了join()
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.