1. 程式人生 > >java的兩種同步方式, Synchronized與ReentrantLock的區別

java的兩種同步方式, Synchronized與ReentrantLock的區別

性能 避免 字節碼 數據 獲取對象 通過 finall 內核 構造函數

java在編寫多線程程序時,為了保證線程安全,需要對數據同步,經常用到兩種同步方式就是Synchronized和重入鎖ReentrantLock。

相似點:

這兩種同步方式有很多相似之處,它們都是加鎖方式同步,而且都是阻塞式的同步,也就是說當如果一個線程獲得了對象鎖,進入了同步塊,其他訪問該同步塊的線程都必須阻塞在同步塊外面等待,而進行線程阻塞和喚醒的代價是比較高的(操作系統需要在用戶態與內核態之間來回切換,代價很高,不過可以通過對鎖優化進行改善)。

區別:

這兩種方式最大區別就是對於Synchronized來說,它是java語言的關鍵字,是原生語法層面的互斥,需要jvm實現。

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

1.Synchronized

Synchronized進過編譯,會在同步塊的前後分別形成monitorenter和monitorexit這個兩個字節碼指令。在執行monitorenter指令時,首先要嘗試獲取對象鎖。如果這個對象沒被鎖定,或者當前線程已經擁有了那個對象鎖,把鎖的計算器加1,相應的,在執行monitorexit指令時會將鎖計算器就減1,當計算器為0時,鎖就被釋放了。如果獲取對象鎖失敗,那當前線程就要阻塞,直到對象鎖被另一個線程釋放為止。

2.ReentrantLock

由於ReentrantLock是java.util.concurrent包下提供的一套互斥鎖,相比Synchronized,ReentrantLock類提供了一些高級功能,主要有以下3項:

1.等待可中斷,持有鎖的線程長期不釋放的時候,正在等待的線程可以選擇放棄等待,這相當於Synchronized來說可以避免出現死鎖的情況。

2.公平鎖,多個線程等待同一個鎖時,必須按照申請鎖的時間順序獲得鎖,Synchronized鎖非公平鎖,ReentrantLock默認的構造函數是創建的非公平鎖,可以通過參數true設為公平鎖,但公平鎖表現的性能不是很好。

3.鎖綁定多個條件,一個ReentrantLock對象可以同時綁定對個對象。

java的兩種同步方式, Synchronized與ReentrantLock的區別