【问题标题】:C++ Boost :Variable sync between 2 threadsC ++ Boost:2个线程之间的变量同步
【发布时间】:2014-08-11 15:52:14
【问题描述】:

我有以下代码:

主线程通知工作线程开始/停止一些工作。在主线程中,触发器是一些 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() 被 'checked' = false 触发时,它不会更新 m_isPlayMode 并且程序变得无响应。我怀疑这是条件竞争问题,因为我正在尝试锁定已经锁定在线程循环中的互斥锁。

我通过从 PlaySlot 方法中删除 unique_lock 并将 m_isPlayMode 转换为原子变量来解决它。它有效。

但我想知道两件事:

  1. 这样的解决方案有什么危险吗?

  2. 可以用其他方法解决吗?

【问题讨论】:

    标签: c++ multithreading boost


    【解决方案1】:

    请注意,m_isPlayMode 受相同的互斥锁保护,因此无法在 worker 运行时更新。为这些或原子使用两个单独的互斥锁。

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

    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);
      }
    }
    

    【讨论】:

    • 你认为在这种情况下原子操作更好吗?
    • @michael-iv 如果您只需要一个标志,那么可能是的。
    • 注意,如果m_mutex是原子的,则不需要将PlaySlot锁定。
    • 如果m_isPlayMode 是一个原子原语,互斥体无关紧要。如果不是,请在使用它的地方周围使用互斥锁。
    • 好吧,在上面的例子中,m_isPlayMode 不是原子的。我不使用原子版本的互斥锁。
    猜你喜欢
    • 2016-07-08
    • 1970-01-01
    • 2013-08-10
    • 1970-01-01
    • 2017-12-08
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多