【问题标题】:Prevent race condition防止竞争条件
【发布时间】:2012-11-29 10:08:11
【问题描述】:

我写了一个定时器,它的工作方式如下: 使用计时器的类实现了回调函数call_()。 计时器在单独的线程中运行,并在计时器到期时执行call_()

我的测试程序如下:

void TestCase::loop()
{
  unique_lock<mutex> lock(*this);

  while(running_)
  {
     timer_->SetTimer(time);
     signal_.wait(lock);
     do_something();
  }
}

void TestCase::call_()
{
  signal_.notify_all();
}

如果 time 非常小(例如 2 毫秒),则测试程序有时会执行 do_something(),有时则不会(在测试程序的不同运行中)。

我的猜测是竞争条件,似乎如果 time 很小,则 call()_signal_.wait(lock) 之前执行(因此 signal_.notify_all() )。

如果我在signal_.notify_all() 之前添加this_thread::sleep(posix_time::milliseconds(2))do_something() 几乎在每次运行中都会执行,对于 sleep(5) 来说一切正常。

如何确保signal_.wait(lock)signal_.notify_all() 之前执行?

【问题讨论】:

  • 你在哪里改变running_的值?我的猜测是您的问题与该变量有关。
  • 如果你必须确保 'wait' 在 'notify' 之前执行,这是错误的信号类型。你需要一个线程安全的条件变量。
  • 测试程序running_在构造函数中设置为true,在TestCase的析构函数中设置为false
  • 请提供一个工作,嗯,编译的例子
  • @ActiveTrayPrntrTagDataStrDrvr:这是我的第一个想法 :-) 我用过boost::conditional_variable signal_ boost 有线程安全的条件变量吗?我在文档中没有找到任何内容。

标签: c++ multithreading boost


【解决方案1】:

如果超时值非常小,则无法保证主线程在定时器线程执行signal_.notify_all 语句之前到达signal_wait 语句。

当您使用一次性计时器时,更好的选择是使用信号量而不是条件变量来同步两个线程。

正如您在条件变量中看到的那样,必须执行等待和通知的顺序才能使机制正常工作。

使用信号量,执行等待的线程也将停止,直到另一个线程发布信号量,但没有要求到达等待和发布操作的顺序。如果首先到达该帖子,则等待立即返回(并且成功)。

【讨论】:

  • 谢谢,这解决了我的问题。我犹豫不决自己实现信号量类,因为我不确定 boost 是否提供更简单的解决方案(因为 boost 中没有信号量)
  • Boost.Interprocess 库中有信号量。您可以使用Barrier 而不是信号量(这只是让两个线程互相等待,而不是只有线程 A 直到线程 B 通过某个点)
猜你喜欢
  • 1970-01-01
  • 2016-03-21
  • 1970-01-01
  • 2014-05-27
  • 1970-01-01
  • 1970-01-01
  • 2019-02-23
  • 2016-12-10
  • 1970-01-01
相关资源
最近更新 更多