1. 程式人生 > >執行緒基礎之遺漏和擴充套件部分

執行緒基礎之遺漏和擴充套件部分

原文地址  譯文地址   譯者:姚志彬  校對:丁一,方騰飛

       這裡我們只是關注了一些多執行緒之間共享變數的簡單使用問題。這些是任何一個寫多執行緒程式的人,都應該熟悉的最基礎的問題。我們忽略了一些其他多執行緒實現提供的工具。它們雖然很少被用到,但是對於你的程式仍然很有必要。

其他鎖型別

大多數環境提供可重入鎖,即被一個單執行緒多次持有,比如java synchronized 塊就有這種鎖的特性行為。通常讀寫鎖也提供這個功能,即一個鎖可以同時被多個“讀”執行緒持有,但只能同時被一個“寫”執行緒持有。

條件變數等

對於一個執行緒等待某個特殊條件符合要求,條件變數時最普遍的機制,比如等待一個共享佇列是不為空的。這些提供wait()呼叫來釋放並且重新獲取一個鎖,掛起執行緒一段時間,直到它被另個執行緒喚醒(”notified” or signalled”)。如果一個執行緒不能被正確喚醒,條件變數很容易引入死鎖到應用程式。因此它們應該被謹慎的運用。但如果我們的關注點只是我們的程式而不是產生的錯誤結果,一個wait(cv, lock

)呼叫行為就如同一個unlock(lock)加lock(lock)的序列。​從而新的問題與這篇文章非常正交。

非阻塞鎖獲取

大多數語言或者執行緒庫提供一個trylock()原函式,可以獲得一個鎖,像lock()的功能​,或者返回一個錯誤的提示,但它從來不會阻塞,這非常容易被我們的模型容納,我們允許trylock()返回一個錯誤的提示,即使這個鎖是可獲得,或者至少是我們程式碼的原因,雖然這有可能發生。​ 因為一些微妙的原因這個假設不允許通過程式實現 ,否則可以看出順序一致性的錯覺 ,​類似觀察申請鎖時呼叫超時。實際上,不允許在程式碼中濫用trylock(),並且應該去用其他一些原語。

從順序一致性“逃離”

很多語言允許通過侵犯順序一致性來獲取同步變數,即使程式不包含資料競爭。很多平臺用這些來顯著提升效能,以一個更復雜的程式模型為代價,在這裡我們不討論該問題。例如java.util.concurrent.atomic‘s lazySet() (Java 6 +) and weakCompareAndSet() 允許一些實現以和順序一致性違背的方式來進行重排序​。C++0x atomic objects 支援記憶體排序限定引數的操作,它們大部分和順序一致性違背。

歷史和致謝

順序一致性概念是被Lamport引入的,How to Make a Multiprocessor Computer that Correctly Executes Multiprocess Programs

.​ sequential-consistency-for-data-race-free-programs方式從一開始就已經是​Ada程式設計模型的​基礎。它作為一個被機器架構有效支撐的模型大約20年前​被Sarita Adve​研究的更詳細。(See for example Adve and Hill, Weak Ordering – A New Definition, ISCA 1990.) ​如我們以上所指出的,Posix執行緒模型至少和它相似,但是很多Posix使用者不知道這一點。​​我們相信windows native 執行緒模型也是取向和它類似,但是直到最近還沒有關於該主題的很多討論。

最近幾年java和C++0x記憶體模型是明確的基於這種方式實現的。​除了這些方面的論文作者,還有主要的貢獻者包括Lawrence Crowl, Doug Lea, Paul McKenney, Clark Nelson, Bratin Saha, and Herb Sutter.​

Paul McKenney也發表了一篇​“frequently asked questions”文章,內容和這篇文章類似。​Sarita Adve在實現章節提供一些內容​。我們也借用了Herb Sutter例子。

很多讀者在早期的草稿中​提供了有用的評論。​Rob Schreiber提供了特殊的擴充套件。