kali鎖屏後無法喚醒 自旋鎖與互斥鎖的微妙差別

2021-10-14 03:02:00 字數 2805 閱讀 7778

互斥鎖是一種實現執行緒同步的機制:當乙個執行緒嘗試獲取互斥鎖,如果互斥鎖已經被占用則該執行緒會被掛起進入睡眠狀態,直到被喚醒。執行緒被掛起時,cpu會將該執行緒當前的處理狀態儲存到記憶體中,等到喚醒時從記憶體中讀取上次的處理狀態,這個cpu切換執行緒處理狀態的過程被稱為「上下文切換」。上下文切換是乙個非常耗時的操作,它需要相當多的cpu指令才能完成。但在早期單核處理器中,只能通過這個方式來完成,畢竟一口鍋不能同時炒兩盤不一樣的菜。

多核處理器開始普及之後,使用互斥鎖經常會出現一種尷尬的情況:乙個執行緒因為嘗試獲取互斥鎖失敗而進入睡眠狀態,但上下文切換還沒完成或者說剛切換上下文沒多久,另乙個執行緒就已經釋放了那個互斥鎖(所以出現了自旋鎖)。

自旋鎖是為實現保護共享資源而提出一種鎖機制。其實,自旋鎖與互斥鎖比較類似,它們都是為了解決對某項資源的互斥使用。無論是互斥鎖,還是自旋鎖,在任何時刻,最多只能有乙個保持者,也就說,在任何時刻最多只能有乙個執行單元獲得鎖。但是兩者在排程機制上略有不同。對於互斥鎖,如果資源已經被占用,資源申請者只能進入睡眠狀態。但是自旋鎖不會引起呼叫者睡眠,如果自旋鎖已經被別的執行單元保持,呼叫者就一直迴圈在那裡看是否該自旋鎖的保持者已經釋放了鎖,」自旋」一詞就是因此而得名。

當乙個執行緒嘗試獲取自旋鎖時,如果自旋鎖已經被占用則該執行緒會一直迴圈等待並反覆檢查鎖是否可用,直到鎖可用時才會退出迴圈。如果持有鎖的執行緒很快就釋放了並且執行緒競爭不激烈,那自旋的效率就非常好,反之,自旋就會白白浪費cpu的處理時間,這反而會帶來效能上的損失。

如果某個執行緒持有鎖的時間過長,就會導致其它等待獲取鎖的執行緒進入迴圈等待,消耗cpu。使用不當會造成cpu使用率極高。

不公平的鎖(即無法滿足等待時間最長的執行緒優先獲取鎖)就會存在」執行緒飢餓」問題。

在用自旋鎖時有可能造成死鎖,當遞迴呼叫時有可能造成死鎖,呼叫有些其他函式也可能造成死鎖,如 copy_to_user()、copy_from_user()、kmalloc()等

說明:我們要慎重使用自旋鎖,自旋鎖只有在核心可搶占式或smp的情況下才真正需要,在單cpu且不可搶占式的核心下,自旋鎖的操作為空操作。自旋鎖適用於鎖使用者保持鎖時間比較短的情況下。

自旋鎖不會使執行緒狀態發生切換,一直處於使用者態,即執行緒一直都是active的;不會使執行緒進入阻塞狀態,減少了不必要的上下文切換,執行速度快(非自旋鎖在獲取不到鎖的時候會進入阻塞狀態,從而進入核心態,當獲取到鎖的時候需要從核心態恢復,需要執行緒上下文切換)

單cpu非搶占核心下: 自旋鎖會在編譯時被忽略(因為單cpu且非搶占模式情況下,不可能發生程序切換,時鐘只有乙個程序處於臨界區(自旋鎖實際沒什麼用了)

單cpu搶占核心下: 自選鎖僅僅當作乙個設定搶占的開關(因為單cpu不可能有併發訪問臨界區的情況,禁止搶占就可以保證臨街區唯一被擁有)

多cpu下: 此時才能完全發揮自旋鎖的作用,自旋鎖在核心中主要用來防止多處理器中併發訪問臨界區,防止核心搶占造成的競爭。

互斥鎖:執行緒會從sleep(加鎖)——>running(解鎖),過程中有上下文的切換,cpu的搶占,訊號的傳送等開銷。

自旋鎖:執行緒一直是running(加鎖——>解鎖),死迴圈檢測鎖的標誌位。

用一句話概括互斥鎖和自旋鎖:互斥鎖是睡等,自旋鎖是忙等

效能問題

互斥鎖的起始原始開銷要高於自旋鎖,但是基本是一勞永逸,臨界區持鎖時間的大小並不會對互斥鎖的開銷造成影響,而自旋鎖是死迴圈檢測,加鎖全程消耗cpu,起始開銷雖然低於互斥鎖,但是隨著持鎖時間,加鎖的開銷是線性增長。

釋放問題

自旋鎖你不需要操心鎖持有進(線)程意外結束(加鎖到解鎖過程中程序被kill了)的時候,鎖的釋放問題(需要寫點**)

互斥鎖最好用於那種生命週期特別長和特別穩定的**段,例如中斷處理例程核心**。

其它(互斥鎖看做二元訊號量)

訊號量和讀寫訊號量適合於保持時間較長的情況,它們會導致呼叫者睡眠,因而自旋鎖適合於保持時間非常短的情況

自旋鎖可以用於中斷,不能用於程序上下文(會引起死鎖)。而訊號量不允許使用在中斷中,而可以用於程序上下文。

自旋鎖保持期間是搶占失效的,自旋鎖被持有時,核心不能被搶占,而訊號量和讀寫訊號量保持期間是可以被搶占的。

互斥鎖(互斥鎖用於臨界區持鎖時間比較長的操作,比如下面這些情況都可以考慮)

臨界區有io操作

臨界區**複雜或者迴圈量大

被保護的共享資源只在程序上下文訪問

臨界區競爭非常激烈

單核處理器

自旋鎖主要用在臨界區持鎖時間非常短且cpu資源不緊張的情況下,自旋鎖一般用於多核的伺服器。

被保護的共享資源需要在中斷上下文訪問(包括底半部(中斷處理控制代碼)和頂半部(軟中斷))

自旋鎖的初衷就是:在短期間內進行輕量級的鎖定。乙個被爭用的自旋鎖使得請求它的執行緒在等待鎖重新可用的期間進行自旋(特別浪費處理器時間),所以自旋鎖不應該被持有時間過長。如果需要長時間鎖定的話, 最好使用訊號量。

既然互斥鎖與自旋鎖各有優劣,我們可以把它們結合到一起:當乙個執行緒獲取鎖失敗,先讓它自旋一段時間,一段時間過後還未能獲取鎖,再讓它進入睡眠狀態。這個過程的重點在於自旋時間的長短,過長可能退化成單純的自旋鎖,過短可能退化成互斥鎖。

讀寫鎖與自旋鎖

一 讀寫鎖 1 特點 讀寫鎖比mutex有更高的適用性,可以多個執行緒同時占用讀模式的讀寫鎖,但是只能乙個執行緒占用寫模式的讀寫鎖。1 當讀寫鎖是寫加鎖狀態時,在這個鎖被解鎖之前,所有試圖對這個鎖加鎖的執行緒都會被阻塞 2 當讀寫鎖在讀加鎖狀態時,所有試圖以讀模式對它進行加鎖的執行緒都可以得到訪問權...

互斥鎖與自旋鎖

一 互斥鎖 當鎖時可用的,呼叫上鎖的api會成功,並且將鎖設定為不再可用。當乙個程序嘗試獲取不可用的鎖的時候它會阻塞,直到鎖被釋放。進入臨界區時獲得鎖,退出臨界區時釋放鎖。二 自旋鎖 是指當乙個執行緒在獲取鎖的時候,如果鎖已經被其它執行緒獲取,那麼該執行緒將迴圈等待,然後不斷的判斷鎖是否能夠被成功獲...

自旋鎖與互斥鎖

互斥鎖,就是悲觀鎖,保證乙個執行緒進去。執行緒會從sleep 加鎖 runng 解鎖 過程中有上下文的切換,cpu的搶占,訊號的傳送等開銷。自旋鎖 執行緒一直都是running 加鎖 解鎖 死迴圈檢測鎖位的標誌位,機制不複雜。自旋鎖 由於自旋鎖使用者一般保持鎖時間非常短,因此選擇自旋鎖而不是睡眠是非...