- 輕量級鎖加鎖
線程在執行同步塊之前,JVM 會先在當前線程的棧幀中創建用于存儲鎖記錄的空間,并將對象頭中的 Mark Word 復制到鎖記錄中,官方稱為 Displaced Mark Word。然后線程嘗試使用 CAS 將對象頭中的 Mark Word 替換為指向鎖記錄的指針。如果成功,當前線程獲得鎖,如果失敗,表示其他線程競爭鎖,當前線程便嘗試使用自旋來獲取鎖。 -
輕量級鎖解鎖
輕量級解鎖時,會使用原子的 CAS 操作將 Displaced Mark Word 替換回對象頭,如果成功,則表示沒有競爭發生。如果失敗,表示當前鎖存在競爭,鎖就會膨脹成重量級鎖。下乳是兩個線程同時競爭鎖,導致鎖膨脹的流程圖。
2.png
因為自旋會消耗 CPU,為了避免無用的自旋(比如獲得鎖的線程被阻塞住了),一旦線程升級成重量級鎖,就不會再恢復到輕量級鎖狀態。當鎖處于這個狀態下,其他線程嘗試獲取鎖,都會被阻塞住,當持有鎖的線程釋放鎖之后會喚醒這些線程,被喚醒的線程會進行新一輪的奪鎖之爭。
- 鎖的優缺點對比
鎖 | 優點 | 缺點 | 使用場景 |
---|---|---|---|
偏向鎖 | 加鎖和解鎖不需要額外的消耗,和執行非同步方法相比僅存在納秒級的差距 | 如果線程間存在鎖競爭,會帶來額外的鎖撤銷的消耗 | 適用于只有一個線程訪問同步塊場景 |
輕量級鎖 | 競爭的線程不會阻塞,提高了線程的相應速度 | 如果始終得不到鎖競爭的線程,使用自旋會消耗CPU | 追求相應時間,同步塊執行的速度非常快 |
重量級鎖 | 線程競爭不使用自旋,不會消耗CPU | 線程阻塞,響應時間緩慢 | 追求吞吐量,同步塊執行時間較長。 |