我应该选择什么样的同步方案来避免在实时,c++ /MFC应用程序上的死锁



我想问你一个问题,关于我应该选择哪种并发设施(CMutex, CSemaphore, CEvent),以使c++/MFC,应用程序多线程。

这是一个实时的机器视觉应用程序,现在需要并发执行,它需要重构,从它以前的单线程状态。

我的工作流的单个迭代如下。我有2个生产者A,B (MFC工人),需要填充两个独立的数据结构(每个1)。第三个线程,一个消费者(MFC Worker)被阻塞,直到两个数据从A和B可用。然后,生产者A和B必须阻塞(每个,在他们的数据完成后),C必须唤醒,执行计算,解除阻塞A和B以继续并再次阻塞,等待下一个段。

  1. 我不能使用队列(类似actor) -阻塞是必需的(
  2. 我试过CEvent,它可以工作。AutoResetEvents for A,B来解锁A在C上调用CMultiLock,然后在C上调用ManualResetEvent->Set()解除阻塞A和B等待后一个事件。我担心的是什么时候重置此事件(例如,A错过了整个Set,然后重置)
  3. 复数为2的信号量是否代表更好的解决方案?

问好。

C必须等待两件事发生,所以最合乎逻辑的事情是等待两个自动复位的CEvent对象:一个由A设置,一个由b设置。

当C完成后,A和B必须各自等待通知。由于有两个线程,并且都必须唤醒,自然的事情是使用另一对自动复位的CEvent对象,A和b各一个,然后C可以在完成后设置两者。

一个计数为2的信号量可以用于唤醒C——C等待两次,A和B都通知——但这意味着C必须在第一个通知之后唤醒,以便等待第二个通知,这是不理想的。

使用计数为2的信号量唤醒a和B之后有可能被盗唤醒和混乱。C向该信号量发出两次信号。A唤醒并接收信号,进行处理并通知C,然后再次等待信号量。由于B还没有被唤醒,这个信号量仍然是可用的,所以A再次使用它。同时,B不会被卡住,因为它不会得到另一个信号,C也会被卡住,因为它会等待B的下一个值。

另一种选择是使用Windows条件变量API而不是事件,但似乎没有一个MFC包装器。见http://msdn.microsoft.com/en-us/library/ms682052%28VS.85%29.aspx

我会对您的选项2进行稍微修改-在两个事件上使用CMultiLock来阻止C;然后使用另一对事件来阻止A和b。C将设置两个自动重置事件来唤醒A和b。然后你不再有重置的竞争。

我提出了一个信号系统,使用一个由互斥锁保护的计数器。这使得所有的同步工作被限制在一个不做其他事情的小类中。

A starts
A writes A-Data
A signals
A stops
B starts
B writes B-Data
B signals 
B stops
C starts
C reads A-Data and B-Data
C starts A, B
C stops

*Signal Class*
Mutex protected counter attribute
Receives signal for A, increment counter
Receives signal for B, increment counter
IF counter equals 2,  clear counter and start C

您可以简单地使用CEvent对象,然后使用WaitForMultipleObjects(),它允许您通过第三个参数'bWaitAll'等待两个对象。

http://msdn.microsoft.com/en-us/library/windows/desktop/ms687025%28v=vs.85%29.aspx

最新更新