1. 程式人生 > >演算法/資料結構

演算法/資料結構

引言

最近對於注重效能的應用程式,我們有了一種能顯著提高程式效能的選擇:多執行緒.執行緒的概念實際上已經存在了很長時間.在過去,多數計算機只有一個處理器,執行緒主要用於將一個大的任務拆分成一系列更小的執行單元.以使得當其中某些執行單元因為等待資源而被阻塞的時候剩餘的執行單元能繼續執行。舉個示例,一個網路應用程式,它監聽一個TCP埠,當有外部請求到達時,處理請求.對於一個單執行緒的應用程式來說,只能在處理完一個請求之後再處理另外的請求,顯然這個應用程式對使用者非常不友好,它為一個使用者服務的時候別的使用者就只能乾等.而對於多執行緒解決方案,我們可以讓另外的執行緒來處理接收到的請求,主執行緒繼續等待在服務埠上接受新的請求.

在只有一個處理器的機器上,一個多執行緒應用程式可能無法達到我們對它的預期.因為所有的執行緒都要爭搶處理器以獲得執行機會.而它的效能說不定比一個用單執行緒方式去解決同樣問題的程式還要差,因為執行緒之間的通訊和資料共享也有不小的開銷.

而在一個對稱多處理器機器上(SMP),一個多執行緒應用可以真正的實現多工並行執行.每個執行緒都可以擁有單獨的處理器以獲得執行的機會,不需要再像單處理器一樣,必須要等到處理器空閒才能獲得執行機會.對一個有N個處理器的SMP系統來說,理論上一個N執行緒的應用程式只需要它的單執行緒版本的1/N的時間就可以完成相同的任務(實際上這個理論值是無法達到的,因為執行緒之間的通訊和資料共享有不小的開銷).

SMP的機器在過去是非常昂貴的,只有一些大公司和組織才能負擔得起.而現今,多核心處理器已經相當廉價(現今市場上的pc處理器至少都擁有一個以上的核心),所以讓應用程式並行化以提高效能現在已經變得非常流行.

但是編寫多執行緒應用程式顯然不是一件簡單的事.執行緒之間需要共享資料,互相通訊,很快你就會發現又要面對以前就遇到過的老問題:死鎖, 對共享資料的非法訪問,多執行緒動態分配/釋放記憶體等.如果你足夠幸運,參與到一個對效能有極高要求的專案中,你將會遇到更多導致效能不達標的問題:

  • Cache顛簸(Cache trashing)
  • 在同步機制上的爭搶.佇列
  • 動態記憶體分配

本文主要介紹一種基於陣列實現的無鎖佇列用於解決上述三個效能問題,特別是動態記憶體分配,因為此無鎖佇列最初的設計目的就是為了解決這個問題.

Continue reading “基於迴圈陣列的無鎖佇列”