14 關於鎖的inflate

前言

呵呵 我們知道 jdk1.6 的時候對 synchronized 關鍵字的處理做了很多優化, 因此關於 synchronized 多了很多的名詞, 偏向鎖, 輕量級鎖, 自旋鎖, 重量級鎖 等等 

 

09 給對象添加偏向鎖的調試

10 偏向鎖的退出的調試

11 偏向鎖的重入 以及 線程1獲取偏向鎖並釋放線程2獲取鎖 的調試

12 給對象添加輕量級鎖的調試

13 輕量級鎖的重入 以及 線程1獲取輕量級鎖並釋放線程2獲取鎖 的調試

前面 我們也做了一些 偏向鎖, 輕量級鎖 的相關調試, 那麼 我們這裏 便來看一下 鎖的膨脹 

 

主要的場景有 

1. 偏向鎖 膨脹成 輕量級鎖 

2. 輕量級鎖 膨脹成 重量級鎖 

 

以下代碼 截圖, 基於 jdk 9 

 

 

偏向鎖 膨脹成 輕量級鎖

偏向鎖 膨脹成 輕量級鎖 主要有一些情況吧 

1. 線程1 獲取對象的偏向鎖執行完成, 線程2 獲取對象的鎖, 線程2 獲取到輕量級鎖
2. 線程1 獲取對象的偏向鎖未執行完成 線程2 獲取對象的鎖, 線程1的偏向鎖 升級爲輕量級鎖

接下來 我們便來調試一下 如上的一些場景 

 

線程1 獲取對象的偏向鎖執行完成, 線程2 獲取對象的鎖, 線程2 獲取到輕量級鎖

測試用例如下  

package com.hx.test04;

/**
 * Test27MultiThreadInBiasLock
 *
 * @author Jerry.X.He <[email protected]>
 * @version 1.0
 * @date 2020-04-03 15:14
 */
public class Test27MultiThreadInBiasLock implements Cloneable {

  // identStr
  private String identStr = "xyz";
  int f01;
  int f02;
  int f03;
  int f04;
  int f05;

  // Test25SynchronizeObject
  public static void main(String[] args) throws Exception {

    Test27MultiThreadInBiasLock lockObj = new Test27MultiThreadInBiasLock();

    doClone(lockObj);
    synchronized (lockObj) {

    }

    new Thread() {
      @Override
      public void run() {
        doClone(lockObj);
        synchronized (lockObj) {

        }
      }
    }.start();

    Test25SynchronizeObject.sleep(2000);
  }

  // doClone
  private static void doClone(Test27MultiThreadInBiasLock obj) {
    try {
      obj.clone();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

}

 

在 synchronizer.cpp fast_enter 裏面加上斷點, 斷點信息如下 

現在是 main 線程獲取了 lockObj 的偏向鎖, 並釋放了, 然後 線程0 來獲取 lockObj 的鎖 

發現 lockObj 偏向於 線程0 然後需要處理 撤銷偏向鎖的相關業務, 以及鎖升級 

 

一下爲當前場景下面 取消 lockObj 的核心代碼 

從偏向線程的 線程棧 中獲取 BasicObjectLock, 查找 BasicObjectLock.obj 爲 lockObj 的 BasicObjectLock 信息 

main線程 偏向鎖退出的時候 清理了 BasicObjectLock.obj, 因此 這裏找不到 BasicObjectLock(表示偏向鎖已經退出)

然後 這裏之後是將 對象頭更新爲了 無鎖狀態(不支持偏向) 

這裏返回的是 偏向鎖已經撤銷 

回到 synchronizer.cpp fast_enter, cond 爲 已撤銷, 那麼 接着走 後面的 slow_enter 的流程 

 

一下爲 synchronizer.cpp slow_enter 的相關代碼 

這裏發現 lockObj 無鎖狀態(不支持偏向), 線程0 嘗試 添加輕量級鎖, 添加輕量級鎖 成功 

線程0  獲取到 lockObj 的輕量級鎖 

 

 

線程1 獲取對象的偏向鎖未執行完成 線程2 獲取對象的鎖, 線程1的偏向鎖 升級爲輕量級鎖

我們調整一下用例 

package com.hx.test04;

/**
 * Test27MultiThreadInBiasLock
 *
 * @author Jerry.X.He <[email protected]>
 * @version 1.0
 * @date 2020-04-03 15:14
 */
public class Test27MultiThreadInBiasLock implements Cloneable {

  // identStr
  private String identStr = "xyz";
  int f01;
  int f02;
  int f03;
  int f04;
  int f05;

  // Test25SynchronizeObject
  public static void main(String[] args) throws Exception {

    Test27MultiThreadInBiasLock lockObj = new Test27MultiThreadInBiasLock();

    doClone(lockObj);
    synchronized (lockObj) {

      new Thread() {
        @Override
        public void run() {
          doClone(lockObj);
          synchronized (lockObj) {

          }
        }
      }.start();

      Test25SynchronizeObject.sleep(2000);

    }
    
  }

  // doClone
  private static void doClone(Test27MultiThreadInBiasLock obj) {
    try {
      obj.clone();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

}

 

線程0 進入 synchronized.cpp fast_enter 

 

線程0  撤銷偏向鎖的相關代碼 

線程0  嘗試獲取鎖的時候, main 線程還未退出 代碼同步塊, 因此 main 線程中的 main 方法的棧幀中 會存在一個 obj 爲 lockObj 的 BasicObjectLock, 這裏 找到了這一個記錄, highest_lock 

然後 因爲 main 線程 現在持有鎖, 因此 將持有的偏向鎖 升級成爲了 輕量級鎖 

然後這裏 返回的是 偏向鎖已經撤銷(升級成了輕量級鎖) 

 

線程0 來到 slow_enter 這裏  

obj() 的偏向鎖被 main 線程持有

線程0 來獲取鎖的時候, 發現 輕量級鎖已經被持有 並且不是被當前線程持有 

走了 inflate 的流程, 當然 我們這裏主要看的是 main 線程持有的 偏向鎖 升級爲 輕量級鎖 的流程 

 

 

輕量級鎖 膨脹成 重量級鎖 

線程1 獲取對象的偏向鎖未執行完成 線程2 獲取對象的鎖, 線程1的鎖 升級爲重量級鎖

測試用例 和 線程1 獲取對象的偏向鎖未執行完成 線程2 獲取對象的鎖, 線程1的偏向鎖 升級爲輕量級鎖 的這個測試用例相同, 只是我們這裏 看的是 線程0 接下來讓 鎖 膨脹成爲重量級鎖的過程 

線程0 走了後面的 ObjectSynchronizer::inflate 的流程, 將鎖升級爲了 重量級鎖 

設置 owner 爲 輕量級鎖 對應的 BasicObjectLock 

然後 在重量級鎖的 monitorenter, monitorexit 的處理中, 對於 owner 爲某一個線程 或者 owner 爲某一個線程的 BasicObjectLock 都進行了兼容處理 

所以 確保了 膨脹成了了 重量級鎖 之後, 之後的 monitorenter, monitorexit 能夠正確的處理 

 

 

重量級鎖的 monitorenter, monitorexit 的 owner 爲 THREAD 或者 BasicLockObject 的處理

 

 

完 

 

 

參考

09 給對象添加偏向鎖的調試

10 偏向鎖的退出的調試

11 偏向鎖的重入 以及 線程1獲取偏向鎖並釋放線程2獲取鎖 的調試

12 給對象添加輕量級鎖的調試

13 輕量級鎖的重入 以及 線程1獲取輕量級鎖並釋放線程2獲取鎖 的調試

 

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