2011-12-28 76 views
3

我有兩個線程,一個用於數據採集,另一個用於顯示。爲了避免不必要的同步。我使用雙緩衝(或翻頁)如下:如何在多線程應用程序中同步雙緩衝

  1. 數據線程寫入緩衝器1而顯示線程讀緩衝器2
  2. 一次寫入一個緩衝完成後,數據線切換到另一個緩衝器(緩衝區2)並開始寫入新頁面。
  3. 對於讀取,如果一個緩衝區處於寫入過程中,顯示​​線程將從另一個緩衝區讀取數據。

它實際上運行良好,但有時(每100幀1)我可以看到在顯示器上撕裂,這意味着仍然存在競爭條件。

那麼如何實現這個雙緩衝的最小(有效)同步呢?僞算法對我來說就足夠了。

+0

除非您的GUI庫爲您完成,否則您還需要根據顯卡的刷新信號同步雙緩衝。否則,如果在重新繪製顯示的同時顯示器刷新,仍可能看到一些「撕裂」。 – 2011-12-28 03:19:35

回答

1

您可以用兩個信號燈做到這一點。它是Producer/Consumer問題的變體。我提供的鏈接中的僞代碼。

+0

它是有道理的。謝謝! – 2011-12-28 03:07:33

+0

我沒有使用信號燈,而是沒有任何鎖定,但更簡單的隊列結構。它工作完美。 – 2011-12-28 04:52:54

+0

嗯。我懷疑你解決了這個問題。也許你減少了競爭條件的機會,但沒有同步原語,我懷疑你可以有一個100%的萬無一失的解決方案。 – Miguel 2011-12-28 07:18:53

1

您正在使用哪種語言,平臺和(如有必要)Graphics API?

僞算法對我來說就足夠了。

根據情況有多種方法,你應該更具體一些。例如,您可以聲明關鍵部分,以便在線程2正在讀取時寫入線程1,等等 - 但有理由不這樣做。

您可以使用消息傳遞,這會喚醒繪圖線程而不是使用關鍵部分。所以它在很大程度上取決於語言,平臺和圖形API。

下面是一個使用消息傳遞到渲染和傳輸同步到顯卡的一些代碼:

DataAcquisitionThread.Run() { 
    ProcessData(); 
    Wait(message); 
    DrawToBackBuffer(); 
} 

DisplayThread.Run() { 
    Wait(message); 
    SwapBuffer(message.bufferNumber); 
    Render(buffer); 
    SendMessage(message.defaultMessage()); 
} 
+0

@Paul:我添加了一個消息傳遞的方法。我曾經使用它來在沒有線程調度系統的系統上同步音頻緩衝區(相反,發送消息會交換正在運行的線程/進程)。 – 2011-12-28 03:16:54