轉自ReentrantLock可重入鎖的使用場景

摘要

從使用場景的角度出發來介紹對ReentrantLock的使用,相對來講容易理解一些。安全

場景1:若是發現該操做已經在執行中則再也不執行(有狀態執行)

a、用在定時任務時,若是任務執行時間可能超過下次計劃執行時間,確保該有狀態任務只有一個正在執行,忽略重複觸發。
b、用在界面交互時點擊執行較長時間請求操做時,防止屢次點擊致使後臺重複執行(忽略重複觸發)。jvm

以上兩種狀況多用於進行非重要任務防止重複執行,(如:清除無用臨時文件,檢查某些資源的可用性,數據備份操做等)性能

1 private ReentrantLock lock = new ReentrantLock();
01                 if (lock.tryLock()) {  //若是已經被lock,則當即返回false不會等待,達到忽略操做的效果 
02
03                     try {
04
05                        //操做
06
07                     finally {
08                         lock.unlock();
09                     }
10
11                 }


場景2:若是發現該操做已經在執行,等待一個一個執行(同步執行,相似synchronized)

這種比較常見你們也都在用,主要是防止資源使用衝突,保證同一時間內只有一個操做可使用該資源。
但與synchronized的明顯區別是性能優點(伴隨jvm的優化這個差距在減少)。同時Lock有更靈活的鎖定方式,公平鎖與不公平鎖,而synchronized永遠是公平的優化

這種狀況主要用於對資源的爭搶(如:文件操做,同步消息發送,有狀態的操做等)spa

ReentrantLock默認狀況下爲不公平鎖操作系統

1 private ReentrantLock lock = new ReentrantLock(); //參數默認false,不公平鎖
2 private ReentrantLock lock = new ReentrantLock(true); //公平鎖
1 try {
2     lock.lock(); //若是被其它資源鎖定,會在此等待鎖釋放,達到暫停的效果
3
4    //操做
5
6 finally {
7     lock.unlock();
8 }

不公平鎖與公平鎖的區別:線程

公平狀況下,操做會排一個隊按順序執行,來保證執行順序。(會消耗更多的時間來排隊)
不公平狀況下,是無序狀態容許插隊,jvm會自動計算如何處理更快速來調度插隊。(若是不關心順序,這個速度會更快)設計


場景3:若是發現該操做已經在執行,則嘗試等待一段時間,等待超時則不執行(嘗試等待執行)

這種其實屬於場景2的改進,等待得到鎖的操做有一個時間的限制,若是超時則放棄執行。
用來防止因爲資源處理不當長時間佔用致使死鎖狀況(你們都在等待資源,致使線程隊列溢出)。code

01                 try {
02                     if (lock.tryLock(5, TimeUnit.SECONDS)) {  //若是已經被lock,嘗試等待5s,看是否能夠得到鎖,若是5s後仍然沒法得到鎖則返回false繼續執行
03
04
05                         try {
06
07
08                             //操做
09
10
11                         finally {
12                             lock.unlock();
13                         }
14
15
16                     }
17                 catch (InterruptedException e) {
18                     e.printStackTrace(); //當前線程被中斷時(interrupt),會拋InterruptedException                 
19                 }
20
21
22
23  <div>
24
25
26
27
28  </div>
29 <span></span>


場景4:若是發現該操做已經在執行,等待執行。這時可中斷正在進行的操做馬上釋放鎖繼續下一操做。

synchronized與Lock在默認狀況下是不會響應中斷(interrupt)操做,會繼續執行完。lockInterruptibly()提供了可中斷鎖來解決此問題。(場景2的另外一種改進,沒有超時,只能等待中斷或執行完畢)隊列

這種狀況主要用於取消某些操做對資源的佔用。如:(取消正在同步運行的操做,來防止不正常操做長時間佔用形成的阻塞)

1 try {
2     lock.lockInterruptibly();
3     //操做
4
5 catch (InterruptedException e) {
6     e.printStackTrace();
7 finally {
8     lock.unlock();
9 }


可重入概念

若一個程序或子程序能夠「安全的被並行執行(Parallel computing)」,則稱其爲可重入(reentrant或re-entrant)的。即當該子程序正在運行時,能夠再次進入並執行它(並行執行時,個別的執行結果,都符合設計時的預期)。可重入概念是在單線程操做系統的時代提出的。

相關文章
相關標籤/搜索