1. 程式人生 > >鎖機制-自旋鎖、偏向鎖、輕量級鎖、重量級鎖

鎖機制-自旋鎖、偏向鎖、輕量級鎖、重量級鎖

自旋鎖

如果持有鎖的執行緒能在很短時間內釋放鎖資源,那麼那些等待競爭鎖的執行緒就不需要做核心態和使用者態之間的切換進入阻塞掛起狀態,只需讓執行緒執行一個忙迴圈(自旋),等持有鎖的執行緒釋放鎖後即可立即獲取鎖,這樣就避免使用者執行緒和核心的切換的消耗。
自旋等待不能代替阻塞,自旋等待本身雖然避免了執行緒切換的開銷,但是要佔用處理器時間,因此如果鎖被佔用時間很短,自旋等待效果就會非常好,但如果鎖被佔用的時間很長,那麼自旋的執行緒只會白白消耗處理器資源,不會有任何有用的工作,反而會帶來效能上的浪費。

偏向鎖

在沒有實際競爭的情況下,還能夠針對部分場景繼續優化。如果不僅僅沒有實際競爭,自始至終使用鎖的執行緒都只有一個,那麼維護輕量級鎖都是浪費的。偏向鎖的目標是,減少無競爭且只有一個執行緒使用鎖的情況下,使用輕量級鎖產生的效能消耗。輕量級鎖每次申請、釋放鎖都至少需要一次CAS,但偏向鎖只有初始化時需要執行一次CAS。偏向鎖假定將來只有第一個申請鎖的執行緒會使用鎖(不會有任何執行緒再來申請鎖),因此只需要在Mark Word中CAS記錄owner(執行緒ID),記錄成功則偏向鎖獲取成功,記錄鎖狀態為偏向鎖,以後當前執行緒等於owner就可以零成本地直接獲得鎖;否則說明有其他執行緒競爭,膨脹為輕量級鎖。
特點

:只有等到執行緒競爭出現才釋放偏向鎖,持有偏向鎖的執行緒不會主動釋放偏向鎖。之後的執行緒競爭偏向鎖,會先檢查持有偏向鎖的執行緒是否存活,如果不存活,則物件變為無鎖狀態,重新偏向;如果仍存活,則偏向鎖升級為輕量級鎖,此時輕量級鎖由原持有偏向鎖的執行緒持有,繼續執行其同步程式碼,而正在競爭的執行緒會進入自旋等待獲得該輕量級鎖。

輕量級鎖

輕量級鎖的目標就是減少無實際競爭情況下,使用重量級鎖產生的效能消耗,包括系統呼叫引起的核心態與使用者態切換、執行緒阻塞造成的執行緒切換等。輕量級鎖是相對於重量級鎖而言的。使用輕量級鎖時,不需要申請互斥量,僅僅將Mark Word中的部分位元組CAS更新指向執行緒棧中的Lock Record,如果更新成功,則輕量級鎖獲取成功,記錄鎖狀態為輕量級鎖;否則,說明已經有執行緒獲得了輕量級鎖,目前發生了鎖競爭(不適合繼續使用輕量級鎖),接下來膨脹為重量級鎖。

重量級鎖

底層通過作業系統的mutex lock實現。等待鎖的執行緒會被阻塞,由於Linux下Java執行緒與作業系統核心態執行緒一一對映,所以涉及到使用者態和核心態的切換、作業系統核心態中的執行緒的阻塞和恢復。這種方式的成本非常高,因此後來稱這種鎖為“重量級鎖”。synchronized就屬於這種鎖。