1. 程式人生 > 其它 >Oracle HWM分析及處理

Oracle HWM分析及處理

併發程式設計中,鎖是經常需要用到的,今天我們一起來看下Java中的鎖機制:synchronizedlock

synchronized

Synchronized 是Java 併發程式設計中很重要的關鍵字,另外一個很重要的是 volatileSyncronized 的目的是一次只允許一個執行緒進入由他修飾的程式碼段,從而允許他們進行自我保護

Synchronized 很像生活中的鎖例子,進入由Synchronized 保護的程式碼區首先需要獲取 Synchronized 這把鎖,其他執行緒想要執行必須進行等待Synchronized 鎖住的程式碼區域執行完成後需要把鎖歸還,也就是釋放鎖,這樣才能夠讓其他執行緒使用。

它提供了⼀種獨佔的加鎖⽅式Synchronized獲取和釋放鎖由JVM實現,⽤戶不需要顯示的釋放鎖,⾮常⽅便。然⽽synchronized也有⼀定的侷限性:

  • 當執行緒嘗試獲取鎖的時候,如果獲取不到鎖會⼀直阻塞。屬於是一種悲觀鎖

  • 如果獲取鎖的執行緒進⼊休眠或者阻塞,除⾮當前執行緒異常,否則其他執行緒嘗試獲取鎖必須⼀直等待。

synchronized可以鎖程式碼塊、方法和物件

  • 方法宣告時使用,放在範圍操作符之後,返回型別宣告之前。即一次只能有一個執行緒進入該方法,其他執行緒要想在此時呼叫該方法,只能排隊等候。當作用於靜態方法時,鎖住的是Class例項,又因為Class的相關資料儲存在永久帶PermGen
    (jdk1.8 則是 metaspace),永久帶是全域性共享的,因此靜態方法鎖相當於類的一個全域性鎖,會鎖所有呼叫該方法的執行緒;
private int number;
public synchronized void numIncrease(){
  number++;
}
  • 你也可以在某個程式碼塊上使用 Synchronized 關鍵字,表示只能有一個執行緒進入某個程式碼段。
public void numDecrease(Object num){
  synchronized (num){
    number++;
  }
}
  • synchronized後面括號裡是一物件,鎖住的是所有以該物件為鎖的程式碼塊,此時執行緒獲得的是物件鎖。
public void test() {
  synchronized (this) {
    // ...
  }
}

lock

Lock 是 Java併發程式設計中很重要的一個(Lock interface)介面,它要比 synchronized 關鍵字更能直譯"鎖"的概念,Lock需要手動加鎖和手動解鎖,一般通過 lock.lock() 方法來進行加鎖, 通過 lock.unlock() 方法進行解鎖。Lock 還有更強大的功能,例如,它的 tryLock 方法可以非阻塞方式去拿鎖。

Lock接⼝⽐同步⽅法和同步塊提供了更具擴充套件性的鎖操作。他們允許更靈活的結構,可以具有完全不同的性質,並且可以⽀持多個相關類的條件物件。

它的優勢有:

  • 可以使鎖更公平
  • 可以使執行緒在等待鎖的時候響應中斷
  • 可以讓執行緒嘗試獲取鎖,並在⽆法獲取鎖的時候⽴即返回或者等待⼀段時間,不會造成死鎖。
  • 可以在不同的範圍,以不同的順序獲取和釋放鎖

Lock 關聯密切的鎖有 ReentrantLockReadWriteLock

ReetrantLock 實現了Lock介面,它是一個可重入鎖,內部定義了公平鎖與非公平鎖

可重⼊鎖是指同⼀個執行緒可以多次獲取同⼀把鎖ReentrantLocksynchronized都是可重⼊鎖。

可中斷鎖是指執行緒嘗試獲取鎖的過程中,是否可以響應中斷synchronized不可中斷鎖,⽽ReentrantLock提供了中斷功能。

公平鎖指多個執行緒同時嘗試獲取同⼀把鎖時,獲取鎖的順序按照執行緒達到的順序。

⾮公平鎖允許執行緒“插隊”synchronized⾮公平鎖,⽽ReentrantLock的預設實現是⾮公平鎖,但是也可以設定為公平鎖。

ReentrantLock它是JDK 1.5之後提供的API層⾯的互斥鎖,需要lock()和unlock()⽅法配合try/finally語句塊來完成。

等待可中斷避免,出現死鎖的情況(如果別的執行緒正持有鎖,會等待引數給定的時間,在等待的過程中,如果獲取了鎖定,就返回true,如果等待超時,返回false)

公平鎖與⾮公平鎖多個執行緒等待同⼀個鎖時,必須按照申請鎖的時間順序獲得鎖,Synchronized鎖⾮公平鎖,

ReentrantLock預設的建構函式是建立的⾮公平鎖,可以通過引數true設為公平鎖,但公平鎖表現的效能不是很好。

ReadWriteLock 一個用來獲取讀鎖,一個用來獲取寫鎖。也就是說將檔案的讀寫操作分開,分成2個鎖來分配給執行緒,從而使得多個執行緒可以同時進行讀操作ReentrantReadWirteLock實現了ReadWirteLock介面,並未實現Lock介面。

總結

  1. synchronized是Java內建的一個關鍵字,Lock是是一個Java介面
  2. synchronized無法判斷獲取鎖的狀態,而lock鎖可以判斷是否獲取到了鎖
  3. synchronized回自動釋放鎖,而lock必須手動釋放鎖。如果不釋放就會變成死鎖
  4. synchronized 執行緒1(獲得鎖,阻塞)執行緒2(傻傻地等待),lock就不一定會等待
  5. synchronized 可重入鎖,不可以中斷的,非公平。lock鎖 可重入鎖,可以判斷鎖,公平不公平自己可以設定
  6. synchronized適合鎖少量的程式碼同步問題 Lock適合鎖大量的同步程式碼

本文來自部落格園,作者:{BearBrick0},轉載請註明原文連結:{https://www.cnblogs.com/bearbrick0}