ReentrantLock 和 synchronized 對比:

java除了使用關鍵字synchronized外,還可以使用ReentrantLock實現獨佔鎖的功能。而且ReentrantLock相比synchronized而言功能更加豐富,使用起來更爲靈活,也更適合複雜的併發場景。這篇文章主要是從使用的角度來分析一下ReentrantLock。

一、簡介

ReentrantLock常常對比着synchronized來分析,我們先對比着來看然後再一點一點分析。

(1)synchronized是獨佔鎖,加鎖和解鎖的過程自動進行,易於操作,但不夠靈活。ReentrantLock也是獨佔鎖,加鎖和解鎖的過程需要手動進行,不易操作,但非常靈活。

(2)synchronized可重入,因爲加鎖和解鎖自動進行,不必擔心最後是否釋放鎖;ReentrantLock也可重入,但加鎖和解鎖需要手動進行,且次數需一樣,否則其他線程無法獲得鎖。

(3)synchronized不可響應中斷,一個線程獲取不到鎖就一直等着;ReentrantLock可以相應中斷。

ReentrantLock好像比synchronized關鍵字沒好太多,我們再去看看synchronized所沒有的,一個最主要的就是ReentrantLock還可以實現公平鎖機制。什麼叫公平鎖呢?也就是在鎖上等待時間最長的線程將獲得鎖的使用權。通俗的理解就是誰排隊時間最長誰先執行獲取鎖。

字數寫得多可能大家都會煩,乾脆直接上代碼演示。

二、使用

1、簡單使用

我們先給出一個最基礎的使用案例,也就是實現鎖的功能。

 

在這裏我們定義了一個ReentrantLock,然後再test方法中分別lock和unlock,運行一邊就可以實現我們的功能。這就是最簡單的功能實現,代碼很簡單。我們再看看ReentrantLock和synchronized不一樣的地方,那就是公平鎖的實現。

2、公平鎖實現

對於公平鎖的實現,就要結合着我們的可重入性質了。公平鎖的含義我們上面已經說了,就是誰等的時間最長,誰就先獲取鎖。

 

首先new一個ReentrantLock的時候參數爲true,表明實現公平鎖機制。在這裏我們多定義幾個線程ABCDE,然後再test方法中循環執行了兩次加鎖和解鎖的過程。

 

3、非公平鎖實現

非公平鎖那就隨機的獲取,誰運氣好,cpu時間片輪到哪個線程,哪個線程就能獲取鎖,和上面公平鎖的區別很簡單,就在於先new一個ReentrantLock的時候參數爲false,當然我們也可以不寫,默認就是false。直接測試一下

 

4、響應中斷

響應中斷就是一個線程獲取不到鎖,不會傻傻的一直等下去,ReentrantLock會給予一箇中斷迴應。在這裏我們舉一個死鎖的案例。

首先我們定義一個測試類ReentrantLockTest3。

 

在這裏我們定義了兩個鎖lock1和lock2。然後使用兩個線程thread和thread1構造死鎖場景。正常情況下,這兩個線程相互等待獲取資源而處於死循環狀態。但是我們此時thread中斷,另外一個線程就可以獲取資源,正常地執行了。

 

我們運行測試一下:

 

5、限時等待

這個是什麼意思呢?也就是通過我們的tryLock方法來實現,可以選擇傳入時間參數,表示等待指定的時間,無參則表示立即返回鎖申請的結果:true表示獲取鎖成功,false表示獲取鎖失敗。我們可以將這種方法用來解決死鎖問題。

首先還是測試代碼,不過在這裏我們不需要再去中斷其中的線程了,我們直接看線程類是如何實現的。

 

在這個案例中,一個線程獲取lock1時候第一次失敗,那就等10毫秒之後第二次獲取,就這樣一直不停的調試,一直等到獲取到相應的資源爲止。

當然,我們可以設置tryLock的超時等待時間tryLock(long timeout,TimeUnit unit),也就是說一個線程在指定的時間內沒有獲取鎖,那就會返回false,就可以再去做其他事了。

OK,到這裏我們就把ReentrantLock常見的方法說明了,所以其原理,還是主要通過源碼來解釋。而且分析起來還需要集合AQS和CAS機制來分析。我也會在下一篇文章來分析。感謝大家的持續關注和支持。

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