互斥鎖 自旋鎖 自適應自旋鎖

互斥鎖:

從 實現原理上來講,Mutex屬於sleep-waiting類型的鎖。例如在一個雙核的機器上有兩個線程(線程A和線程B),它們分別運行在Core0和 Core1上。假設線程A想要通過pthread_mutex_lock操作去得到一個臨界區的鎖,而此時這個鎖正被線程B所持有,那麼線程A就會被阻塞 (blocking),Core0 會在此時進行上下文切換(Context Switch)將線程A置於等待隊列中,此時Core0就可以運行其他的任務(例如另一個線程C)而不必進行忙等待。而Spin lock則不然,它屬於busy-waiting類型的鎖,如果線程A是使用pthread_spin_lock操作去請求鎖,那麼線程A就會一直在 Core0上進行忙等待並不停的進行鎖請求,直到得到這個鎖爲止。


自旋鎖(Spin lock)

自旋鎖與互斥鎖有點類似,只是自旋鎖不會引起調用者睡眠,如果自旋鎖已經被別的執行單元保持,調用者就一直循環在那裏看是 否該自旋鎖的保持者已經釋放了鎖,"自旋"一詞就是因此而得名。其作用是爲了解決某項資源的互斥使用。因爲自旋鎖不會引起調用者睡眠,所以自旋鎖的效率遠 高於互斥鎖。雖然它的效率比互斥鎖高,但是它也有些不足之處:
    1、自旋鎖一直佔用CPU,他在未獲得鎖的情況下,一直運行--自旋,所以佔用着CPU,如果不能在很短的時 間內獲得鎖,這無疑會使CPU效率降低。
    2、在用自旋鎖時有可能造成死鎖,當遞歸調用時有可能造成死鎖,調用有些其他函數也可能造成死鎖,如 copy_to_user()、copy_from_user()、kmalloc()等。
因此我們要慎重使用自旋鎖,自旋鎖只有在內核可搶佔式或SMP的情況下才真正需要,在單CPU且不可搶佔式的內核下,自旋鎖的操作爲空操作。自旋鎖適用於鎖使用者保持鎖時間比較短的情況下。


自旋鎖是一種非阻塞鎖,也就是說,如果某線程需要獲取自旋鎖,但該鎖已經被其他線程佔用時,該線程不會被掛起,而是在不斷的消耗CPU的時間,不停的試圖獲取自旋鎖。

互斥量是阻塞鎖,當某線程無法獲取互斥量時,該線程會被直接掛起,該線程不再消耗CPU時間,當其他線程釋放互斥量後,操作系統會激活那個被掛起的線程,讓其投入運行。

兩種鎖適用於不同場景:

如果是多核處理器,如果預計線程等待鎖的時間很短,短到比線程兩次上下文切換時間要少的情況下,使用自旋鎖是划算的。

如果是多核處理器,如果預計線程等待鎖的時間較長,至少比兩次線程上下文切換的時間要長,建議使用互斥量。

如果是單核處理器,一般建議不要使用自旋鎖。因爲,在同一時間只有一個線程是處在運行狀態,那如果運行線程發現無法獲取鎖,只能等待解鎖,但因爲自身不掛起,所以那個獲取到鎖的線程沒有辦法進入運行狀態,只能等到運行線程把操作系統分給它的時間片用完,纔能有機會被調度。這種情況下使用自旋鎖的代價很高。

如果加鎖的代碼經常被調用,但競爭情況很少發生時,應該優先考慮使用自旋鎖,自旋鎖的開銷比較小,互斥量的開銷較大。

自適應自旋鎖(Adaptive spinning)


Adaptive spinning is an optimization technique where a two-phase spin-then-block strategy is used by threads attempting a contended synchronized enter operation. This technique enables threads to avoid undesirable effects that impact performance such as context switching and repopulation of Translation Lookaside Buffers (TLBs). It is “adaptive" because the duration of the spin is determined by policy decisions based on factors such as the rate of success and/or failure of recent spin attempts on the same monitor and the state of the current lock owner.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章