Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 多线程死锁:这种设计会导致死锁吗?_C++_Multithreading - Fatal编程技术网

C++ 多线程死锁:这种设计会导致死锁吗?

C++ 多线程死锁:这种设计会导致死锁吗?,c++,multithreading,C++,Multithreading,线程A:设置变量m_bPaused,m_pPauseEvent是一个信号量对象,它提供wait()和set()接口。 线程调用此暂停: 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_pPa

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

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 
   }
    m_bPaused = false;    //A3

    m_pPauseEvent->Set(); //A4 
并调用线程A以继续线程B:

    m_bPaused = false;    //A3

    m_pPauseEvent->Set(); //A4 

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

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

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

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

  • 如前所述,您访问m_bPaused可能是一个问题
  • 线程B在
    Wait(0)
    之前调用
    Set()。您确定线程A将得到通知,还是线程B使用了通知
  • 在几乎所有的多线程类中都存在伪尾流的问题。您的线程B似乎没有受到保护

  • 因此,很难判断此代码是否无死锁。

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

  • 如前所述,您访问m_bPaused可能是一个问题
  • 线程B在
    Wait(0)
    之前调用
    Set()。您确定线程A将得到通知,还是线程B使用了通知
  • 在几乎所有的多线程类中都存在伪尾流的问题。您的线程B似乎没有受到保护

  • 因此很难判断此代码是否无死锁。

    Windows事件不能保证信号唤醒当前的一个等待者。这是导致
    PulseEvent
    已知问题和未唤醒的原因,因为事件已设置,然后被清除,但等待的线程可能看不到该设置


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

    Windows事件不保证信号唤醒当前的一个等待者。这是导致
    PulseEvent
    已知问题和未唤醒的原因,因为事件已设置,然后被清除,但等待的线程可能看不到该设置


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

    如果我将m\u bPaused打包到多线程安全,所有问题都会解决吗?“打包”?还有一个更大的问题。线程B中的代码是否在循环中执行?也就是说,
    (m\u bPaused)
    是否重复测试?如果我将m\u bPaused打包到多线程安全,所有问题是否都会得到解决?“打包”?还有一个更大的问题。线程B中的代码是否在循环中执行?也就是说,
    (m\u bPaused)
    是否重复测试?您的事件是手动重置还是自动重置。这将带来不同,尤其是对于这段代码。顺便说一句,你需要的(老实说)是一个条件变量+互斥对。特别是在线程B中。您需要能够设置条件(使用另一个名称的谓词通知)并作为原子操作开始等待。我可以确定这是手动重置。您的事件是手动重置还是自动重置。这将带来不同,尤其是对于这段代码。顺便说一句,你需要的(老实说)是一个条件变量+互斥对。特别是在线程B中。您需要能够设置条件(使用另一个名称的谓词通知)并作为原子操作开始等待。我可以确定这是手动重置。+1。事实上,我认为基于Set()-Wait()的假设,A将在B单独消费之前消费它,这暗示了这可能是DL。如果可以,您必须假设它会,因此需要修复它。
    EventTypeWrapper EventWindows::Wait(unsigned long maxTime){unsigned long res=WaitForSingleObject(_event,maxTime);}
    该集合只是调用SetEvent窗口api@MIKU_LINK_SUCCESS:好的,这也不起作用。您不能保证线程A被踢出等待状态。有可能是B设置了事件,并在等待后立即使用自己的设置。+1。事实上,我认为基于Set()-Wait()的假设,A将在B单独消费之前消费它,这暗示了这可能是DL。如果可以,您必须假设它会,因此需要修复它。
    EventTypeWrapper EventWindows::Wait(unsigned long maxTime){unsigned long res=WaitForSingleObject(_event,maxTime);}
    该集合只是调用SetEvent窗口api@MIKU_LINK_SUCCESS:好的,这也不起作用。您不能保证线程A被踢出等待状态。有可能是B设置了事件,并在使用它自己的等待设置之后立即使用。