2011-10-05 40 views
2

我想问你一个关于应该选择哪种并发设施(CMutex,CSemaphore,CEvent)的问题,以便使C++/MFC应用程序成为多线程。我应该选择哪种同步方案来避免实时C++/MFC应用程序出现死锁?

这是一个真正的时间,机器视觉应用程序,现在需要同时执行,它需要重构,从它的前一个单线程的地位。

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

  1. 我不能使用队列(演员类) - 阻塞是一个要求 :(
  2. 我试图CEvent的和它的作品AutoResetEvents为A,B,以解除对C,然后一个 调用的CMultiLock。一个ManualResetEvent-> Set()从C到 取消阻止A和B等待后一个事件。我担心的是什么时候重置这个事件(例如A错过整个Set然后Reset)
  3. Do信号量与多个2可能代表更好的解决方案?

此致敬礼。

回答

2

Ç必须等待两件事情,所以最顺理成章的事情是,它等待了两个自动复位CEvent对象:由B.

另外,在C完成后,A和一组由A和一个B必须等待通知。由于有两个线程,并且两者都必须唤醒,所以自然而然的是使用另一对自动重置对象,对于A和B中的每一个都是一个对象.C可以在完成时设置两个对象。

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

使用与用于唤醒A和B之后的2计数的信号具有用于被盗唤醒窗口和混乱的可能性。 C发信号灯两次。 A唤醒并接收信号,执行处理并通知C,然后再次等待信号量。由于B还没有醒来,信号量仍然可用,所以A再次获取它。同时B没有坚持,因为它不会让另一个信号,和C被卡住,因为它会等待下一个值从B.

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

+0

使用条件变量API将程序限制为仅在Windows Vista(Server 2008)或更高版本上运行 – bdonlan

+0

我将继续处理该问题。我不会做过早的优化;我将首先使用第二对CEvents进行工作。然后我会弄清楚,从用户到内核空间的切换花费多少时间。 关于你的替代点。我真的需要为每个使用的同步对象使用MFC包装器吗?我没有太多的MFC并发应用程序的经验。 –

+0

另一件与我有关的事情是C工作者的取消,你如何安全地逃脱锁定,没有类似MsgWaitForMultipleObjects的可警告等待模式? –

2

我会去你的选项2的轻微的修改 - 使用上的CMultiLock两个事件到C座;然后使用事件的另一阻止A和B. C将设置自动重置事件来唤醒每个A和B,那么你不再有复位比赛。

+0

这是一个候选解决方案。事实上最有可能的。虽然,我喜欢通过一次调用来发送所有(都是)入队线程的原子性。 –

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 
相关问题