自旋鎖和互斥鎖是多執行緒程式中的重要概念。 它們被用來鎖住一些共享資源, 以防止併發訪問這些共享資料時可能導致的資料不一致問題。 但是它們的不同之處在**? 我們應該在什麼時候用自旋鎖代替互斥鎖?
理論分析
從理論上說, 如果乙個執行緒嘗試加鎖乙個互斥鎖的時候沒有成功, 因為互斥鎖已經被鎖住了, 這個未獲取鎖的執行緒會休眠以使得其它執行緒可以馬上執行。 這個執行緒會一直休眠, 直到持有鎖的執行緒釋放了互斥鎖, 休眠的執行緒才會被喚醒。 如果乙個執行緒嘗試獲得乙個自旋鎖的時候沒有成功, 該執行緒會一直嘗試加鎖直到成功獲取鎖。 因此它不允許其它執行緒執行(當然, 作業系統會在該執行緒所在的時間片用完時, 強制切換到其它執行緒)。
存在的問題
互斥鎖存在的問題是, 執行緒的休眠和喚醒都是相當昂貴的操作, 它們需要大量的cpu指令, 因此需要花費一些時間。 如果互斥量僅僅被鎖住很短的一段時間, 用來使執行緒休眠和喚醒執行緒的時間會比該執行緒睡眠的時間還長, 甚至有可能比不斷在自旋鎖上輪訓的時間還長。自旋鎖的問題是, 如果自旋鎖被持有的時間過長, 其它嘗試獲取自旋鎖的執行緒會一直輪訓自旋鎖的狀態, 這將非常浪費cpu的執行時間, 這時候該執行緒睡眠會是乙個更好的選擇。
解決方案
在單核/單cpu系統上使用自旋鎖是沒用的, 因為當執行緒嘗試獲取自旋鎖不成功的時候會一直嘗試, 這會一直占用cpu, 其它執行緒不可能執行, 因為其他執行緒不能執行, 這個鎖也就不會被解鎖。 換句話說, 在單核/單cpu的系統上,自旋鎖除了浪費時間沒有一點好處。 這時如果這個執行緒(記為a)可以休眠, 其它執行緒可以立即執行, 因為其它有可能解鎖, 那麼執行緒a可能在喚醒後繼續執行。
在多核/多cpu的系統上, 特別是大量的執行緒只會短時間的持有鎖的時候, 在使執行緒睡眠和喚醒執行緒上浪費大量的時間, 也許會顯著降低程式的執行效能。 使用自旋鎖, 執行緒可以充分利用排程程式分配的時間片(經常阻塞很短的時間, 不用休眠, 然後馬上繼續它們的工作了), 以達到更高的處理能力和吞吐量。
實踐
因為程式設計師往往並不能事先知道哪種方案會更好(比如, 不知道執行環境的cpu核的數量), 作業系統也不知道一段指令是不是針對單核或者多核環境下做過優化, 所以大部分作業系統並不嚴格區分互斥鎖和自旋鎖。 實際上, 絕大部分現代的作業系統採用的是混合型互斥鎖(hybrid mutexes)和混合型自旋鎖(hybrid spinlocks)。 它們是什麼意思呢?
混合型互斥鎖, 在多核系統上起初表現的像自旋鎖一樣, 如果乙個執行緒不能獲取互斥鎖, 它不會馬上被切換為休眠狀態, 因為互斥量可能很快就被解鎖, 所以這種機制會表現的像自旋鎖一樣。 只有在一段時間以後(或者嘗試一定次數,或者其他指標)還不能獲取鎖, 它就會被切換為休眠狀態。 如果執行在單核/單cpu上, 這種機制將不會自旋(就像上面解釋的, 這種情況自旋沒有什麼好處)。
混合型自旋鎖, 起初表現的和正常自旋鎖一樣, 但是為了避免浪費大量的cpu時間, 會有乙個折中的策略。 這種機制不會把執行緒切換到休眠態(既然想要使用自旋鎖, 那麼你並不希望這種情況發生), 也許會決定放棄這個執行緒的執行(馬上放棄或者等一段時間)並允許其他執行緒執行, 這樣提高了自旋鎖被解鎖的可能性(大多數情況, 執行緒之間的切換操作比使執行緒休眠而後喚醒它要昂貴, 儘管那不是很明顯)。
總結
如果對選擇哪種方案感到疑惑, 那就使用互斥鎖吧, 並且大多數現代的作業系統都允許在獲取鎖的時候自旋一段時間(混合型互斥鎖)。 只有在一定條件下使用自旋鎖才可以提高效能, 事實上, 你現在在做的專案可能沒有乙個能在通過自旋鎖提高效能。 也許你考慮使用你自己定義的」鎖物件」, 它可以在內部使用互斥鎖或者自旋鎖(例如: 在建立鎖物件時, 用哪種機制是可配置的), 剛開始在所有的地方都是用互斥鎖, 如果你認為在有些地方用自旋鎖確實可以提高效能, 你可以試試, 並且比較兩種情況的結果(使用一些效能評測工具), 但一定要在單核和多核環境上測試之後再下結論(如果你的**是誇平台的, 也要盡可能在不同的平台上測試下)。
自旋鎖和互斥鎖
1.理論分析 從理論上說,如果乙個執行緒嘗試加鎖乙個互斥鎖的時候沒有成功,因為互斥鎖已經被鎖住了,這個未獲取鎖的執行緒會休眠以使得其它執行緒可以馬上執行。這個執行緒會一直休眠,直到持有鎖的執行緒釋放了互斥鎖,休眠的執行緒才會被喚醒。如果乙個執行緒嘗試獲得乙個自旋鎖的時候沒有成功,該執行緒會一直嘗試加...
互斥鎖與自旋鎖
一 互斥鎖 當鎖時可用的,呼叫上鎖的api會成功,並且將鎖設定為不再可用。當乙個程序嘗試獲取不可用的鎖的時候它會阻塞,直到鎖被釋放。進入臨界區時獲得鎖,退出臨界區時釋放鎖。二 自旋鎖 是指當乙個執行緒在獲取鎖的時候,如果鎖已經被其它執行緒獲取,那麼該執行緒將迴圈等待,然後不斷的判斷鎖是否能夠被成功獲...
自旋鎖與互斥鎖
互斥鎖,就是悲觀鎖,保證乙個執行緒進去。執行緒會從sleep 加鎖 runng 解鎖 過程中有上下文的切換,cpu的搶占,訊號的傳送等開銷。自旋鎖 執行緒一直都是running 加鎖 解鎖 死迴圈檢測鎖位的標誌位,機制不複雜。自旋鎖 由於自旋鎖使用者一般保持鎖時間非常短,因此選擇自旋鎖而不是睡眠是非...