我有一個程式,希望在后臺定時做一些事情,我就寫了一個執行緒,每隔一段時間做一些作業。
作業執行緒的定時作業,是用等待一個條件變數,讓他超時來實作的:
auto r = cvTimer.wait_for(lk, chrono::milliseconds(500));
這樣,每隔500ms就會超時一次,于是我就可以做事情了。
如果我想停止后臺定時做事情,我只要給cvTimer一個信號,那么后臺執行緒就能得到通知,并退出
后臺執行緒可以對auto r = cvTimer.wait_for的回傳值進行檢查,
如果是cv_status::timeout,表示正常作業時間到,
如果回傳不是cv_status::timeout,那么應該就是想要停止作業執行緒。
可是很奇怪,cvTimer.wait_for會隨機回傳cv_status::no_timeout,導致后臺執行緒退出(雖然不是我讓他停止的)
請問大家,這是怎么回事?在我沒有通知的情況下,wait_for怎么就回傳了?
ubuntu下測驗沒有問題(g++7.4),windows下有此問題(vs2019)
#include <iostream>
#include <chrono>
#include <condition_variable>
#include <mutex>
#include <future>
using namespace std;
condition_variable cvTimer;
mutex cvMutex;
future<void> ftReturn;
void WorkThread()
{
unique_lock<mutex> lk(cvMutex);
while (true)
{
auto r = cvTimer.wait_for(lk, chrono::milliseconds(500));
if (cv_status::timeout == r)
{
//這是正常的時間到了,做一些必要的事情
cout << "Do Work" << endl;
}
else
{
//這是退出了,
//但是在我還沒有呼叫StopWork就很有可能會進到這里來
//看檔案好像有虛假喚醒這么一說,
//但是喚醒的代碼只有一處,而且還未呼叫,怎么就喚醒了?
cout << "Stop Work" << endl;
return;
}
}
}
void StartWork()
{
ftReturn = async(launch::async, &WorkThread);
}
void StopWork()
{
unique_lock<mutex> lk(cvMutex);
cvTimer.notify_one();
lk.unlock();
ftReturn.wait();
}
int main()
{
StartWork();
this_thread::sleep_for(chrono::seconds(60));
StopWork();
}
uj5u.com熱心網友回復:
這是windows實作的bug?uj5u.com熱心網友回復:
虛假退出哦!uj5u.com熱心網友回復:
假喚醒是多執行緒常見的一種現象(通常的假喚醒是指多個執行緒同時被喚醒,但是搶到鎖的只能有一個執行緒,所以其他沒搶到鎖的都屬于假喚醒),這里可能是condition_variable本身實作的問題,一般建議不直接這么使用wait_for,要么用wait_for的另一個版本(帶Period引數的版本,通過回傳的Period判斷是否是假醒),要么改成wait_until可以參考以下
https://www.bookstack.cn/read/Cpp_Concurrency_In_Action/content-appendix_D-D.2-chinese.md
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/9559.html
標籤:C++ 語言
上一篇:求助
