IT培訓-高端面授IT培訓機構
          云和教育:云和數據集團高端IT職業教育品牌
          • 國家級
            全民數字素養與技能培訓基地
          • 河南省
            第一批產教融合型企業建設培育單位
          • 鄭州市
            數字技能人才(碼農)培養評價聯盟

          JVM對Java的原生鎖做了哪些優化?

          • 發布時間:
            2023-05-31
          • 版權所有:
            云和教育
          • 分享:

          JVM對Java的原生鎖(即synchronized關鍵字)做了許多優化,其中包括:

          1.偏向鎖(Biased Locking)

          當一個線程獲取鎖后,JVM會將鎖的對象頭標記為偏向鎖。此時,該線程可以無需競爭地獲取該鎖。這種情況下,鎖的獲取和釋放不需要額外的開銷,因為偏向鎖會記錄線程ID,使得在該線程持有鎖期間,其他線程無法獲取該鎖。只有在其他線程嘗試獲取鎖時,才會升級為輕量級鎖。

          2.輕量級鎖(Lightweight Locking)

          當多個線程爭奪鎖時,JVM會將鎖標記為輕量級鎖。此時,JVM會在鎖對象的對象頭中記錄指向線程棧中鎖記錄的指針,以及用于保存原始對象的指針。這樣,當一個線程嘗試獲取該鎖時,JVM會將該線程的棧幀中的鎖記錄與鎖對象頭中的指針進行比較。如果相同,則表示該線程已經獲得了該鎖;否則,JVM會使用CAS操作嘗試將鎖對象頭中的指針指向當前線程的鎖記錄。如果CAS操作成功,表示當前線程成功獲得了鎖。否則,表示有其他線程爭奪該鎖,此時JVM會將鎖升級為重量級鎖。

          3.重量級鎖(Heavyweight Locking)

          當多個線程爭奪鎖時,如果無法獲得鎖,則會升級為重量級鎖。此時,JVM會使用操作系統的互斥量實現鎖。重量級鎖的開銷非常大,因為需要進行用戶態與內核態之間的上下文切換。

          下面是一個簡單的代碼演示,展示了偏向鎖、輕量級鎖和重量級鎖的使用情況。

          public class SynchronizedDemo {
              private int count = 0;
          
              public synchronized void increment() {
                  count++;
              }
          
              public static void main(String[] args) {
                  SynchronizedDemo demo = new SynchronizedDemo();
                  for (int i = 0; i < 100000; i++) {
                      demo.increment();
                  }
                  System.out.println(demo.count);
              }
          }

          在這個示例中,我們使用synchronized關鍵字來對increment()方法進行同步。由于該方法是實例方法,因此鎖對象是該實例對象。當多個線程同時訪問該方法時,JVM會根據鎖的狀態來選擇使用偏向鎖、輕量級鎖或重量級鎖。具體的選擇過程是由JVM內部的鎖升級算法來決定的,這里不再詳細展開。