synchronized與Lock的區別比較

synchronized與Lock的區別比較

1、synchronized 是Java內置的關鍵字,使用後會自動釋放鎖,
Lock是java.util.concurrent.Locks 包下的一個接口,必須要手動釋放。特別是在發生異常時,需要在 finally 塊中進行手動釋放,否則會發生死鎖行爲

2、Lock可響應中斷,而synchronized 不能響應中斷,並且Lock提供了更豐富的方法實現;例如
Lock() ; //獲取鎖
tryLock(); //獲取鎖
tryLock(long time, TimeUnit unit); //在一定時間單位內等待
lockInterruptibly(); //獲取鎖,可響應中斷(AB線程同時獲取鎖,A得到後,B進行等待,則B會被Tread.interrupt()方法中端並可去執行其他的代碼邏輯,而synchronized無法被中端)
unlock(); //釋放鎖

3、synchronized 是非公平鎖,即不能保證等待鎖線程的順序,
Lock的實現 ReentrantLock 可通過實例化true or false 的構造參數實現公平鎖和非公平鎖,默認爲非公平鎖

Lock lock = new ReentrantLock();//	非公平鎖
Lock lock2 = new ReentrantLock(true);//	公平鎖
Lock lock3 = new ReentrantLock(false);// 非公平鎖

4、ReentrantLock是唯一實現了Lock接口的類,並且ReentrantLock提供了更多的方法
在這裏插入圖片描述
5、synchronized無法判斷是否獲取鎖的狀態,Lock可以判斷是否獲取到鎖;

6、Lock鎖適合大量同步的代碼的同步問題,synchronized鎖適合代碼少量的同步問題。

7、都是可重入鎖:在執行對象中所有同步方法不用再次獲得鎖

8、synchronized是一個悲觀鎖,Lock是一個樂觀鎖(底層基於volatile和cas實現)

下面奉上一張表格:

類別 syncronized Lock
存在層次 Java的關鍵字,在jvm層面上 是一個接口
鎖的釋放 1、以獲取鎖的線程執行完同步代碼,釋放鎖
2、線程執行發生異常,jvm會讓線程釋放鎖
在finally中必須釋放鎖,不然容易造成線程死鎖
鎖的獲取 假設A線程獲得鎖,B線程等待。如果A線程阻塞,B線程會一直等待 分情況而定,Lock有多個鎖獲取的方式,具體下面會說道,大致就是可以嘗試獲得鎖,線程可以不用一直等待
鎖狀態 無法判斷 可以判斷
鎖類型 可重入 不可中斷 非公平 可重入 可判斷 可公平(兩者皆可,默認非公平)
性能 少量同步 大量同步

二、底層實現

1、synchronznized映射成字節碼指令就是增加兩個指令:monitorenter、monitorexit,
當一條線程執行時遇到monitorenter指令時,它會嘗試去獲得鎖,如果獲得鎖,那麼所計數器+1(爲什麼要加1,因爲它是可重入鎖,可根據這個瑣計數器判斷鎖狀態),如果沒有獲得鎖,那麼阻塞,
當它遇到一個monitoerexit時,瑣計數器會-1,當計數器爲0時,就釋放鎖
(tips:節碼中出現的兩個monitoerexit指令的原因是:一個正常執行-1,令一個異常時執行,這兩個用goto的方式只執行一個)

2、Lock底層則基於volatile和cas實現

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