實現一個雙緩沖隊列


在生產者-消費者模式中,我們常常會使用到隊列,這個隊列在多個線程共享訪問時存在互斥和競爭操作, 意味着每次訪問都要加鎖。如何更好的如何減少鎖競爭次數呢 ?今天要介紹的雙緩沖隊列就是個不錯的選擇。

雙緩沖隊列就是沖着同步/互斥的開銷來的。我們知道,在多個線程並發訪問同一個資源的時候,需要特別注意線程的同步問題。稍稍不注意,噢貨,程序結果不正確了。

原理

直接上圖:

img

在雙緩沖隊列中,鎖除了起到保護數據安全的作用來,還要承擔線程調度的任務。

  • 雙隊列交換位置和任務入隊列都需要對當前隊列進行操作,因此,他們是互斥的操作。
  • 消費操作放在單獨的線程中,在沒有任務進來時,需要將線程置為等待狀態。

使用兩個信號量,來調度入列隊和交換隊列的操作。同時,我們還需要一個信號量,在沒有任務入隊列時,阻塞整個消費線程。

主要使用 AutoResetEvent,ManualResetEvent,它們的具體使用可以看一下園子里的文章:

http://www.cnblogs.com/springyangwc/archive/2011/10/12/2208991.html

  1. AutoResetEvent.WaitOne()每次只允許一個線程進入,當某個線程得到信號后,AutoResetEvent會自動又將信號置為不發送狀態,則其他調用WaitOne的線程只有繼續等待,也就是說AutoResetEvent一次只喚醒一個線程;
  2. ManualResetEvent則可以喚醒多個線程,因為當某個線程調用了ManualResetEvent.Set()方法后,其他調用WaitOne的線程獲得信號得以繼續執行,而ManualResetEvent不會自動將信號置為不發送;
  3. 也就是說,除非手工調用了ManualResetEvent.Reset()方法,則ManualResetEvent將一直保持有信號狀態,ManualResetEvent也就可以同時喚醒多個線程繼續執行。

實現

我以一個簡單的示例來演示整個過程。

在生產線程中,入隊列一些字符串;使用消費線程,把這些字符串和它所在隊列編號打印出來:

img

img

看一下運行效果:

img

可以看到,在消費線程中,隊列交換使用。

下一篇,我們來實現一個對雙緩沖隊列的封裝。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM