2011-10-05 37 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 
相關問題