多线程死锁:这种设计是否会导致死锁?

时间:2013-01-30 08:51:59

标签: c++ multithreading

线程A:设置变量m_bPaused,m_pPauseEvent是一个提供wait()和set()接口的信号量对象。 线程A调用此方法暂停:

PausePlay(){
    m_bPaused = true;           // A1

    m_pPauseEvent->Wait(0);     //A2 wait for the B thread is enter to the waiting
}

主题B:

    if (m_bPaused)
   {
       m_pPauseEvent->Set();    //B1
       m_pPauseEvent->Wait(0);  //B2 0 wait forever 
   }

并调用线程A继续线程B:

    m_bPaused = false;    //A3

    m_pPauseEvent->Set(); //A4 

当我暂停时,我等到B1被执行。线程A返回。这里是死锁吗?当我在线程A中调用continue时,运行到A3。同时,线程B仍然是B1和B2,那么A完成行m_pPauseEvent-> Set()。线程B永远不会收到A4发送的信号。死锁!这会发生吗?

3 个答案:

答案 0 :(得分:2)

由于您未发布事件类的实现,因此代码中可能存在多个问题。

  1. 如前所述,您对m_bPaused的访问可能是一个问题。
  2. 主题B在Set()之前调用Wait(0)。您确定线程A会收到通知吗或者线程B是否会使用该通知。
  3. 在几乎所有多线程类中都存在虚假唤醒的问题。看来你的线程B没有受到这种保护。
  4. 所以很难判断这段代码是否会无死锁。

答案 1 :(得分:1)

不能肯定地说。 m_bPaused可能是非原子变量,这意味着并发访问是未定义的行为。

答案 2 :(得分:0)

Windows事件不保证信号唤醒当前的服务员之一。这是PulseEvent已知问题和错过唤醒的原因,因为事件已设置然后被清除,但等待线程可能看不到该集。

在这种情况下,Wait调用之后的Set调用可能会唤醒而不是另一个线程上的Wait调用。这意味着没有同步保护对m_bPaused的访问,即UB,也意味着错误的线程已经唤醒。