C ++ Boost:2个线程之间的变量同步

时间:2014-08-11 15:52:15

标签: c++ multithreading boost

我有以下代码:

主线程通知工作线程启动/停止某个作业。在主线程中,触发器是一些UI按钮(在这种情况下是Qt SDK):

    void PlaySlot(bool checked){
        boost::unique_lock<boost::mutex> lock(m_mutex);
        if(checked == true){

            m_isPlayMode = true;
            m_event.notify_one(); //tell thread to  start playing.
         }else{

            m_isPlayMode = false;
        }

    }

现在,在工作线程中,一旦 m_isPlayMode 变为真,一些循环开始运行一段有限的时间,它将在时间结束时退出或 m_isPlayMode 变得虚假。

在线程操作符内:

    while(true)
   {

      boost::unique_lock<boost::mutex> lock(m_mutex);
      m_event.wait(lock); //wait for next event
      if(m_isPlayMode == true){

          while(m_frameIndex< totalFrames && m_isPlayMode){

           m_frameIndex++;
           ///do some work

          }

        m_isPlayMode = false;
        emit playEnded(false);

     }

  }

现在,在循环开始播放之后发生了什么,当PlaySlot()通过&#39;检查&#39; = false它没有更新m_isPlayMode并且程序没有响应。我怀疑条件竞争问题,因为我试图锁定已经锁定在线程循环中的互斥锁。

我通过从 PlaySlot 方法移除 unique_lock 并将m_isPlayMode转换为原子变量来解决它。它可以工作。

但我想知道两件事:

  1. 这样的解决方案是否有任何危险。

  2. 可以用另一种方式解决吗?

1 个答案:

答案 0 :(得分:1)

请注意m_isPlayMode受同一个互斥锁保护,因此在工作程序运行时无法更新。使用两个单独的互斥体,或原子。

编辑快速修复可能会添加第二个互斥锁:

void PlaySlot(bool checked){
    boost::unique_lock<boost::mutex> lock(m_isPlayModeMutex); // <--
    // ...
}

工作线程:

for (;;) {
  boost::unique_lock<boost::mutex> lock(m_mutex);
  m_event.wait(lock); // wait for next event

  boost::unique_lock<boost::mutex> playModeLock(m_isPlayModeLock);
  if(m_isPlayMode == true){
    while(m_frameIndex< totalFrames && m_isPlayMode){
      playModeLock.unlock();
      /// ... (not locked here)
      playModeLock.lock();
    }
    m_isPlayMode = false;
    emit playEnded(false);
  }
}