1. 程式人生 > >Java 鎖機制

Java 鎖機制

當沒有競爭的時候,系統會預設使用偏斜鎖。JVM 利用CAS(compare and swap)在 物件頭的第一部分(mark word)設定 偏向執行緒ID,表示物件偏向於這個執行緒。 因為大部分併發場景下面 物件 生命週期 中最多被一個執行緒鎖定, 使用偏斜鎖的話可以降低 低競爭狀態下的 額外開銷。

這個時候如果有另外的執行緒試圖鎖定已經被傾斜過的物件,JVM會撤銷(revoke)偏斜鎖, 並切換到輕量級鎖。 這時候輕量級鎖 會根據 CAS 操作 Mark word 來試圖 獲取鎖,如果成功就 切換為輕量級鎖;否則 進一步 升級 為重量級鎖。

自旋鎖: 是競爭失敗的執行緒,並不會真實的在作業系統層面掛起等待,而是JVM會讓執行緒做幾次空迴圈(For (;;)),迴圈幾輪後,如果可以獲得鎖,那麼進入臨界區,如果還是不能獲得鎖的話,這時候才會在作業系統掛起等待。 一般在 低競爭並且佔用鎖的時間短的執行緒很實用。是一種在悲觀鎖中的樂觀優化(因為JVM的synchronized是一種悲觀鎖 )。

死鎖: 因為悲觀鎖獨佔CPU的特性,死鎖就是執行緒A在持有鎖A的情況下,試圖進入鎖B; 而執行緒B 在持有 鎖B的情況下,試圖進入鎖A。如下圖:

例如多個巢狀的 synchronized 有可能會發生死鎖的情況。 所以為了避免死鎖, 我們就需要 注意鎖的獲取順序。 或者使用Object.wait() 或者  CountDownLatch.await()等帶超時的方法。在長時間沒有鎖的情況下,即退出邏輯。

另外如果發生死鎖的情況下可以使用jstack等工具去獲取死鎖發生的位置,這裡就不過多闡述。