溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java?Synchronized鎖升級原理及過程源碼分析

發布時間:2023-04-21 14:06:55 來源:億速云 閱讀:178 作者:iii 欄目:編程語言

Java Synchronized鎖升級原理及過程源碼分析

引言

在Java中,synchronized關鍵字是實現線程同步的重要機制。為了在多線程環境下保證數據的一致性和線程安全,synchronized提供了簡單易用的鎖機制。然而,隨著并發量的增加,簡單的鎖機制可能會導致性能瓶頸。為了優化性能,JVM引入了鎖升級的概念,即根據競爭情況動態調整鎖的級別。本文將深入分析Java Synchronized鎖升級的原理及過程,并結合源碼進行詳細解析。

1. Synchronized鎖的基本概念

1.1 鎖的類型

在Java中,synchronized鎖可以分為以下幾種類型:

  • 偏向鎖(Biased Locking):適用于只有一個線程訪問同步塊的場景,減少無競爭情況下的鎖開銷。
  • 輕量級鎖(Lightweight Locking):適用于多個線程交替訪問同步塊的場景,通過CAS操作避免線程阻塞。
  • 重量級鎖(Heavyweight Locking):適用于多個線程競爭訪問同步塊的場景,通過操作系統級別的互斥量實現線程阻塞。

1.2 鎖的升級過程

鎖的升級過程是指從偏向鎖到輕量級鎖,再到重量級鎖的逐步升級過程。JVM會根據線程競爭情況動態調整鎖的級別,以優化性能。

2. 鎖升級的原理

2.1 偏向鎖

偏向鎖的核心思想是:如果一個線程獲得了鎖,那么鎖會偏向這個線程,后續該線程再次獲取鎖時不需要進行任何同步操作。偏向鎖的目的是減少無競爭情況下的鎖開銷。

2.1.1 偏向鎖的獲取

當一個線程首次進入同步塊時,JVM會檢查對象頭的Mark Word,如果發現沒有偏向鎖,則會嘗試通過CAS操作將Mark Word設置為偏向鎖狀態,并記錄線程ID。

2.1.2 偏向鎖的撤銷

如果另一個線程嘗試獲取偏向鎖,JVM會撤銷偏向鎖,并將鎖升級為輕量級鎖。撤銷偏向鎖的過程需要暫停持有偏向鎖的線程(即STW,Stop-The-World)。

2.2 輕量級鎖

輕量級鎖的核心思想是:通過CAS操作避免線程阻塞,適用于多個線程交替訪問同步塊的場景。

2.2.1 輕量級鎖的獲取

當一個線程嘗試獲取輕量級鎖時,JVM會將對象頭的Mark Word復制到線程棧中的鎖記錄(Lock Record)中,然后嘗試通過CAS操作將對象頭的Mark Word替換為指向鎖記錄的指針。如果CAS操作成功,則線程獲取鎖;如果失敗,則說明有其他線程競爭鎖,此時鎖會升級為重量級鎖。

2.2.2 輕量級鎖的釋放

當線程釋放輕量級鎖時,JVM會通過CAS操作將鎖記錄中的Mark Word還原到對象頭中。如果CAS操作失敗,則說明鎖已經升級為重量級鎖,此時需要釋放重量級鎖。

2.3 重量級鎖

重量級鎖的核心思想是:通過操作系統級別的互斥量(Mutex)實現線程阻塞,適用于多個線程競爭訪問同步塊的場景。

2.3.1 重量級鎖的獲取

當一個線程嘗試獲取重量級鎖時,JVM會將對象頭的Mark Word替換為指向重量級鎖的指針,并將線程阻塞,直到鎖被釋放。

2.3.2 重量級鎖的釋放

當線程釋放重量級鎖時,JVM會喚醒等待鎖的線程,并將對象頭的Mark Word還原為無鎖狀態。

3. 鎖升級的源碼分析

3.1 偏向鎖的源碼分析

在HotSpot虛擬機中,偏向鎖的實現主要位于biasedLocking.cpp文件中。以下是偏向鎖獲取和撤銷的關鍵代碼片段:

// 偏向鎖獲取
void ObjectSynchronizer::fast_enter(Handle obj, BasicLock* lock, TRAPS) {
  if (UseBiasedLocking) {
    if (!SafepointSynchronize::is_at_safepoint()) {
      BiasedLocking::revoke_and_rebias(obj, false, THREAD);
    } else {
      BiasedLocking::revoke_at_safepoint(obj);
    }
  }
  // 輕量級鎖獲取
  slow_enter(obj, lock, THREAD);
}

// 偏向鎖撤銷
void BiasedLocking::revoke_and_rebias(Handle obj, bool attempt_rebias, TRAPS) {
  // 撤銷偏向鎖
  if (attempt_rebias) {
    // 嘗試重新偏向
  } else {
    // 撤銷偏向鎖
  }
}

3.2 輕量級鎖的源碼分析

輕量級鎖的實現主要位于interpreterRuntime.cpp文件中。以下是輕量級鎖獲取和釋放的關鍵代碼片段:

// 輕量級鎖獲取
void InterpreterRuntime::monitorenter(JavaThread* thread, BasicObjectLock* elem) {
  Handle h_obj(thread, elem->obj());
  if (UseBiasedLocking) {
    // 偏向鎖處理
  }
  // 輕量級鎖處理
  ObjectSynchronizer::fast_enter(h_obj, elem->lock(), thread);
}

// 輕量級鎖釋放
void InterpreterRuntime::monitorexit(JavaThread* thread, BasicObjectLock* elem) {
  Handle h_obj(thread, elem->obj());
  ObjectSynchronizer::fast_exit(h_obj(), elem->lock(), thread);
}

3.3 重量級鎖的源碼分析

重量級鎖的實現主要位于objectMonitor.cpp文件中。以下是重量級鎖獲取和釋放的關鍵代碼片段:

// 重量級鎖獲取
void ObjectMonitor::enter(TRAPS) {
  // 獲取鎖
  if (TryLock(Self) > 0) {
    // 成功獲取鎖
    return;
  }
  // 阻塞線程
  EnterI(THREAD);
}

// 重量級鎖釋放
void ObjectMonitor::exit(TRAPS) {
  // 釋放鎖
  if (TryRelease(Self) > 0) {
    // 成功釋放鎖
    return;
  }
  // 喚醒等待線程
  ExitEpilog(Self);
}

4. 鎖升級的性能優化

鎖升級的目的是在多線程環境下根據競爭情況動態調整鎖的級別,以優化性能。偏向鎖適用于無競爭場景,輕量級鎖適用于低競爭場景,重量級鎖適用于高競爭場景。通過鎖升級,JVM能夠在不同場景下選擇最合適的鎖機制,從而減少鎖開銷,提高并發性能。

5. 總結

Java Synchronized鎖升級機制是JVM優化并發性能的重要手段。通過偏向鎖、輕量級鎖和重量級鎖的動態升級,JVM能夠在不同競爭場景下選擇最合適的鎖機制,從而減少鎖開銷,提高并發性能。本文通過源碼分析詳細介紹了鎖升級的原理及過程,希望能夠幫助讀者深入理解Java Synchronized鎖機制的工作原理。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女