首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用于信令和等待的condition_variable使用

用于信令和等待的condition_variable使用
EN

Stack Overflow用户
提问于 2021-04-08 00:01:57
回答 1查看 185关注 0票数 1

如果数据竞争不是问题,我可以使用std::condition_variable启动(即信令)和停止(即等待)线程的工作吗?

例如:

代码语言:javascript
运行
复制
std::atomic<bool> quit = false;
std::atomic<bool> work = false;
std::mutex mtx;
std::condition_variable cv;

// if work, then do computation, otherwise wait on work (or quit) to become true
// thread reads: work, quit
void thread1()
{
   while ( !quit )
   {
      // limiting the scope of the mutex
      {
         std::unique_lock<std::mutex> lck(mtx);

         // I want here is to wait on this lambda
         cv.wait(lck, []{ return work || quit; });
      }

      if ( work )
      {
         // work can become false again while working.
         // I want here is to complete the work
         // then wait on the next iteration.
         ComputeWork();
      }
   }
}

// work controller
// thread writes: work, quit
void thread2()
{
   if ( keyPress == '1' )
   {
      // is it OK not to use a mutex here?
      work = false;
   }
   else if ( keyPress == '2' )
   {
      // ... or here?
      work = true;
      cv.notify_all();
   }
   else if ( keyPress == ESC )
   {
      // ... or here?
      quit = true;
      cv.notify_all();
   }
}

Update/Summary:不安全,因为亚当描述的“失去唤醒”场景。cv.wait(lck, predicate());可以等效为while(!predicate()){ cv.wait(lck); }

要更容易地看到问题:while(!predicate()){ /*lost wakeup can occur here*/ cv.wait(lck); }

可以通过将谓词变量的任何读/写放到互斥范围中来修复:

代码语言:javascript
运行
复制
void thread2()
{
   if ( keyPress == '1' )
   {
      std::unique_lock<std::mutex> lck(mtx);
      work = false;
   }
   else if ( keyPress == '2' )
   {
      std::unique_lock<std::mutex> lck(mtx);
      work = true;
      cv.notify_all();
   }
   else if ( keyPress == ESC )
   {
      std::unique_lock<std::mutex> lck(mtx);
      quit = true;
      cv.notify_all();
   }
}
EN

回答 1

Stack Overflow用户

发布于 2021-04-08 01:33:00

不,不安全。等待的线程可以获取互斥对象,检查谓词,看不到需要唤醒的任何内容。然后,信令线程设置bool,并发出信号。接下来,等待线程在cv上阻塞,并且永远不会唤醒。

您必须在触发唤醒lambda条件和通知cv之间的某个点保持互斥锁,以避免出现这种情况。

我没有看过的“向下”(关闭唤醒)的情况,这可能取决于什么行为到底是好的。如果没有在正式意义上指定的内容,我也不会这么做;一般来说,在处理多线程代码时,您至少应该尝试对正确性的正式证明草图,否则您的代码最多只会意外地工作。

如果你不能这样做,找一个可以为你编写代码的人。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66995664

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档