C++ 多线程死锁:这种设计会导致死锁吗?
线程A:设置变量m_bPaused,m_pPauseEvent是一个信号量对象,它提供wait()和set()接口。 线程调用此暂停: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
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
可能是一个非原子变量,这意味着并发访问是未定义的行为。由于您没有发布事件类的实现,因此代码中可能存在多个问题
Wait(0)
之前调用Set()。您确定线程A将得到通知,还是线程B使用了通知
因此,很难判断此代码是否无死锁。由于您没有发布事件类的实现,因此代码中可能存在多个问题
Wait(0)
之前调用Set()。您确定线程A将得到通知,还是线程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设置了事件,并在使用它自己的等待设置之后立即使用。