C++11-condition_variable-wait_until未按预期工作

C++ 11 - condition_variable - wait_until not working as expected

本文关键字:工作 variable-wait until C++11-condition      更新时间:2023-10-16

我已经实现了一个示例程序来了解wait_fo和wait_until在C++11中是如何工作的。

代码-

#include <iostream>
#include <future>
#include <chrono>
#include <mutex>
#include <condition_variable>
#include <thread>
using namespace std;
using namespace std::chrono;
condition_variable cv;
mutex m;
bool flagValue=false;
int sampleFunction(int a)
{
    cout<<"Executing sampleFunction...";
    cout.flush();
    this_thread::sleep_for(seconds(5));
    cout<<"Done."<<endl;
    return a;
}
void sampleFunctionCond(int a)
{
    lock_guard<mutex> lg(m);
    cout<<"Executing sampleFunctionCond...";
    cout.flush();
    this_thread::sleep_for(seconds(5));
    cout<<"Done."<<endl;
    cout<<"Value : "<<a<<endl;
    flagValue=true;
    cv.notify_one();
    return;
}
int main()
{
   unique_lock<mutex> ul(m);
   future<int> f1=async(launch::async,sampleFunction,10);
   future_status statusF1=f1.wait_for(seconds(1));
   if(statusF1==future_status::ready)
    cout<<"Future is ready"<<endl;
   else if (statusF1==future_status::timeout)
    cout<<"Timeout occurred"<<endl;
   else if (statusF1==future_status::deferred)
    cout<<"Task is deferred"<<endl;
   cout<<"Value : "<<f1.get()<<endl;
   cv_status statusF2;
   thread t1(sampleFunctionCond,20);
   t1.detach();
   while(!flagValue)
   {
       statusF2=cv.wait_until(ul,system_clock::now()+seconds(2));
       if(statusF2==cv_status::timeout)
       {
       cout<<"Timeout occurred."<<endl;
       break;
       }
       else
       {
       cout<<"Condition variable is ready or spurious wake up occurred."<<endl;
       }
   }
}

输出-

Executing sampleFunction...Timeout occurred
Done.
Value : 10
Executing sampleFunctionCond...Done.
Value : 20
Timeout occurred.

sampleFunction正在按预期工作,因为它在"完成"之前打印"发生超时",但sampleFunctionCond的情况并非如此。虽然它知道wait_until已经超时,但它在函数sampleFunctionCOnd完成执行后打印消息。

有人能帮我理解吗?谢谢

statusF2=cv.wait_until(...);语句中存在竞争条件。可能发生的情况是等待已经超时,并且即将返回。要返回,它需要重新获取互斥对象。与此同时,另一个线程已经获取了互斥对象。因此,在其他线程将flagValue设置为true并释放互斥之前,statusF2=cv.wait_until(...);不能返回。

要修复代码,在检查等待是否超时之前,必须检查flagValue的值。

函数"sampleFunctionCond"不应该一直持有互斥对象"m"。您可以尝试在"flagValue=true;"行之前立即锁定"m"。