2011-05-03 136 views
219

我認爲兩者都在做同樣的工作,你如何決定使用哪一個進行同步?什麼時候應該使用自旋鎖而不是互斥鎖?

+1

可能重複[Spin​​lock Versus Semaphore!](http://stackoverflow.com/questions/195853/spinlock-versus-semaphore) – 2011-05-03 13:21:28

+7

互斥和信號量不是一回事,所以我不認爲這是一個重複。引用的文章的答案正確地說明了這一點。 欲瞭解更多詳情,請參閱http://www.barrgroup.com/Embedded-Systems/How-To/RTOS-Mutex-Semaphore – nanoquack 2014-04-28 05:05:50

回答

568

理論

從理論上講,當一個線程試圖鎖定一個互斥體,它並沒有成功,因爲互斥已被鎖定,這將轉入休眠狀態,立即允許另一個線程來運行。它會繼續睡覺直到被喚醒,一旦這個互斥鎖被任何線程鎖定之前解鎖,情況就是這樣。當一個線程試圖鎖定一個自旋鎖並且它不成功時,它會不斷地重新嘗試鎖定它,直到它最終成功;因此它不會允許另一個線程取代它的位置(但是,當然,一旦當前線程的CPU運行時間量已超出,操作系統將強制切換到另一個線程)。

的問題

與互斥的問題是,把線程睡眠和覺醒起來又都是相當昂貴的操作,他們將需要相當多的CPU指令,因此還需要一些時間。如果現在互斥鎖只能鎖定很短的時間,那麼將線程休眠並再次喚醒的時間可能會超過線程實際睡眠的時間,甚至可能超過線程的時間因不斷投票自旋而浪費了。另一方面,對自旋鎖進行輪詢會不斷浪費CPU時間,如果鎖持續更長的時間,這將浪費更多的CPU時間,而如果線程正在休眠,則會更好。

單核/單CPU系統上的使用自旋鎖使得通常沒有意義的,因爲只要自旋鎖輪詢阻塞唯一可用的CPU核心,沒有其他線程可以運行和由於沒有其他線程可以運行,鎖也不會被解鎖。 IOW,一個自旋鎖只浪費CPU時間在這些系統上沒有真正的好處。如果線程進入睡眠狀態,另一個線程可能立即運行,可能會解鎖該鎖,然後允許第一個線程繼續處理,一旦它再次醒來。

在一個多核/多CPU系統上,只有很短的時間纔會鎖住大量的鎖,浪費時間不斷地讓線程進入休眠狀態並再次喚醒線程可能會顯着降低運行時性能。當使用自旋鎖代替時,線程有機會利用完整的運行時間量(總是隻在很短的時間段內阻塞,但隨後立即繼續工作),從而導致更高的處理吞吐量。

實踐

因爲很多時候程序員不能提前知道,如果互斥體或自旋鎖會更好(例如,因爲目標架構的CPU核心數量不詳),也不操作系統可以知道,如果一個某些代碼已針對單核或多核環境進行了優化,大多數系統不會嚴格區分互斥和自旋鎖。事實上,大多數現代操作系統都有混合互斥和混合自旋鎖。這實際上意味着什麼?

在多核系統上,混合互斥鎖起初就像一個自旋鎖一樣。如果一個線程無法鎖定互斥鎖,它將不會立即進入睡眠狀態,因爲互斥鎖可能很快就會被解鎖,所以互斥量將首先表現得像一個自旋鎖。只有在特定時間(或重試或任何其他測量因素)後還沒有獲得鎖定時,線程才真正進入睡眠狀態。如果相同的代碼只在一個只有一個內核的系統上運行,那麼互斥量將不會自旋鎖,儘管如上所述,這並不會有好處。

的混合自旋鎖的行爲就像在第一次正常的自旋鎖,但要避免浪費過多的CPU時間,它可能有一個回退的策略。它通常不會讓線程進入睡眠狀態(因爲使用spinlock時不希望發生這種情況),但它可能會決定停止線程(立即或在一段時間後)並允許另一個線程運行,從而增加了自旋鎖解鎖的機會(一個純線程切換通常比一個線程睡眠並稍後再次喚醒線程更便宜,儘管不是很遠)。

摘要

如有疑問,使用互斥,他們通常是更好的選擇,最現代化的系統將允許他們自旋鎖的時間很短的量,如果這似乎是有益的。使用自旋鎖有時可以提高性能,但只有在某些條件下,以及您有疑問的事實才會告訴我,您目前沒有在任何可能有利於自旋鎖的項目上工作。您可以考慮使用自己的「鎖定對象」,即可以使用一個自旋鎖或互斥體內部(例如創建這樣一個對象時,此行爲可能是可配置的),最初使用互斥無處不在,如果你認爲某個地方使用自旋鎖可能真的幫助,給它一個嘗試,並比較結果(例如使用分析器),但要確保你妄下結論(也可能是不同的操作系統之前,如果你的代碼來測試這兩種情況下,單核和多核系統將是跨平臺的)。

+2

精湛的解釋...我對螺旋鎖我有疑問,我可以使用螺旋鎖ISR?如果沒有,爲什麼不是 – haris 2014-03-31 17:45:04

+3

@Mecki如果我沒有弄錯,我相信你在回答中建議時間分片只發生在單處理器系統上。這是不正確的!您可以在單處理器系統上使用自旋鎖,並且它會旋轉直到其時間段到期。然後,另一個具有相同優先級的線程可以接管(就像您對多處理器系統所描述的那樣)。 – fumoboy007 2014-04-08 21:44:14

+5

@ fumoboy007「它會旋轉,直到它的時間量程到期」 //這意味着你浪費CPU時間/電池電量絕對沒有W/O任何單一的好處,這是完全魯鈍。不,我無處說,一次只切發生在單核系統,我在單核系統表示,目前* ONLY *時間分片,而有* REAL *並行OM多核系統(還時間分片,但無關緊要什麼我在我的回覆中寫道);你也完全錯過了混合自旋鎖的概念,以及它爲什麼在單核和多核系統上運行良好。 – Mecki 2014-04-09 13:42:12

6

與Mecki的建議繼續本文pthread mutex vs pthread spinlock亞歷山大·桑德勒的博客,亞歷克斯在Linux上顯示spinlock & mutexes如何可以實現用#ifdef對其進行測試的行爲。

但是,一定要採取根據你的觀察,最後調用,理解爲給出的例子是一個孤立的事件,您的項目需求,環境可能是完全不同的。

5

也請注意,某些環境和條件(如對調度水平> = DISPATCH級別的Windows上運行),則不能使用互斥而是自旋鎖。 關於unix - 同樣的事情。

這裏是競爭對手stackexchange UNIX網站相當於一個問題:在調度上的Windows系統 https://unix.stackexchange.com/questions/5107/why-are-spin-locks-good-choices-in-linux-kernel-design-instead-of-something-more

信息: http://download.microsoft.com/download/e/b/a/eba1050f-a31d-436b-9281-92cdfeae4b45/IRQL_thread.doc

3

自旋鎖和互斥同步機制的今天是很常見的待觀察。

讓我們想想自旋鎖第一。

基本上它是一個忙碌的等待動作,這意味着我們必須等待指定的鎖被釋放,然後才能繼續下一個動作。從概念上來說非常簡單,但實施並非如此。例如:如果鎖沒有被釋放,那麼線程被換出並進入睡眠狀態,我們應該處理它嗎?當兩個線程同時請求訪問時如何處理同步鎖定?

通常,最直觀的想法是通過變量處理同步以保護關鍵部分。互斥體的概念是相似的,但它們仍然不同。重點介紹:CPU利用率。Spinlock消耗CPU時間來等待動作,因此,我們可以總結兩者之間的差異:

在同質多核環境中,如果在臨界區花費的時間比使用Spinlock小,因爲我們可以減少上下文切換時間。 (單核比較並不重要,因爲有些系統在開關中間執行Spinlock)

在Windows中,使用Spinlock會將線程升級到DISPATCH_LEVEL,在某些情況下可能不允許使用,所以這次我們必須使用互斥鎖(APC_LEVEL)。

5

Mecki的回答很不錯。但是,在單個處理器上,當任務正在等待中斷服務例程給出的鎖定時,使用螺旋鎖可能有意義。中斷會將控制權轉移給ISR,ISR將爲等待任務使用的資源做好準備。在將控制權交給被中斷的任務之前,它將通過釋放鎖來結束。旋轉任務會發現可用的螺旋鎖並繼續。

+2

我不確定完全同意此答案。一個單一的處理器,如果一個任務持有資源的鎖,那麼ISR不能安全地繼續進行,並且不能等待任務解鎖資源(因爲持有該資源的任務被中斷)。在這種情況下,任務應該簡單地禁用中斷來強制自身與ISR之間的排斥。當然,這必須在非常短的時間間隔內完成。 – user1202136 2016-09-24 07:29:04

-4

在單核/單CPU系統上使用自旋鎖通常是沒有意義的,因爲只要自旋鎖輪詢阻塞唯一可用的CPU核心,其他線程就不能運行,因爲沒有其他線程可以運行,鎖也不會被解鎖。 IOW,自旋鎖只浪費CPU時間在這些系統上沒有真正的好處

這是錯誤的。在單處理器系統上使用自旋鎖不會浪費CPU週期,因爲一旦進程需要旋轉鎖定,禁用先佔功能,因此可能沒有其他人在旋轉!只是使用它沒有任何意義!因此,Uni系統上的自旋鎖在編譯時被內核取代爲preempt_disable!

+0

引用的內容完全正確。如果源代碼的編譯結果不包含自旋鎖,則引用是無關緊要的。假設你所說的內核在編譯時替換了spinlock,在另一臺可能或不可能是單處理器的機器上預編譯時,spinlock是如何處理的,除非我們嚴格只在內核本身中討論spinlock。 – Hydranix 2016-11-10 19:24:30

+0

「一旦進程發生旋轉鎖定,搶先被禁用」。當進程旋轉時,搶先未被禁用。如果是這樣的話,一個進程就可以通過輸入一個螺旋鎖來停止整個機器,並且永遠不會離開。請注意,如果您的線程運行在內核空間(而不是用戶空間)中,則採用旋轉鎖確實會禁用搶佔,但我不認爲這就是在這裏討論的內容。 – 2016-12-30 02:36:03

+0

在*編譯時*由內核*? – Shien 2017-06-09 17:20:42