我应该选择哪种同步方案来避免实时C ++ / MFC应用程序出现死锁?

时间:2011-10-05 16:27:24

标签: c++ mfc concurrency synchronization

我想问一个关于应该选择哪种并发工具(CMutex,CSemaphore,CEvent)的问题,以使C ++ / MFC应用程序成为多线程。

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

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

  1. 我不能使用队列(类似Actor) - 阻塞是必需的 :(
  2. 我尝试了CEvent并且它有效。 A,B的AutoResetEvents取消阻止a CMultiLock调用C然后从C调用ManualResetEvent-> Set() 取消阻止A和B等待后一事件。我担心的是什么时候 重置此事件(如果A错过整个Set然后重置。)
  3. 多个2的信号量是否可以代表更好的解决方案?
  4. 最好的问候。

4 个答案:

答案 0 :(得分:2)

我会稍微修改你的选项2 - 在两个事件上使用CMultiLock来阻止C;然后使用另一个事件来阻止A和B.C会设置两个自动重置事件来唤醒A和B中的每一个。然后你不再参加比赛重置。

答案 1 :(得分:2)

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

当C完成时,A和B必须各自等待通知。由于有两个线程,并且两个线程都必须唤醒,所以自然就是使用另一对自动重置CEvent对象,每个对象分别对应A和B.然后,C可以在完成时设置它们。 / p>

计数为2的信号量可用于唤醒C --- C等待两次,A和B中的每一个都通知---但这意味着C必须在第一次通知后醒来才能等待第二,这不太理想。

使用计数为2的信号量来唤醒A和B后,可能会导致被唤醒和混乱。 C两次发信号通知信号量。唤醒并接收信号,进行处理并通知C,然后再次等待信号量。由于B尚未唤醒,信号量仍然可用,所以A再次接受它。同时B没有卡住,因为它不会得到另一个信号,而C卡住了,因为它会等待B的下一个值。

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

答案 2 :(得分:0)

我建议使用由互斥锁保护的计数器的信号系统。这使得所有同步工作都局限于一个没有其他的小类。

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

答案 3 :(得分:0)

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

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