重入鎖(ReentrantLock)
ReentrantLock
重入鎖使用java.util.concurrent.locks.ReentrantLock類來實現。它的幾個重要方法如下:
lock():獲得鎖,如果鎖已經被佔用,則等待。 lockInterruptibly():獲得鎖,但優先響應中斷。 tryLock():嘗試獲得鎖,如果成功,返回true,失敗返回false。該方法不等待,立即返回。 tryLock(long time, TimeUnit unit):在給定時間內嘗試獲得鎖。 unLock():釋放鎖。
對於重入鎖,同一個執行緒可以多次獲得鎖,但是釋放鎖的時候,也必須釋放相同次數。否則會產生異常。
Condition條件
通過Condition的newCondition()方法可以生成一個與當前重入鎖繫結的Condition例項。利用Condition物件,我們就可以讓執行緒在合適的時間等待,或者在某一個特定的時間得到通知,繼續執行。
await() 方法會是當前執行緒等待,同時釋放當前鎖,當其他執行緒中使用signal() 或signalAll() 方法時,執行緒會重新獲得鎖並繼續執行。或者當執行緒被中斷時,也能跳出等待;signal() 方法用於喚醒一個在等待中的執行緒。
當執行緒使用Condition.await時,要求執行緒持有相關的重入鎖,在Condition.await呼叫後,這個執行緒會釋放這把鎖。同理,在Condition.signal方法呼叫時,也要求執行緒先獲得相關的鎖。在signal方法呼叫後,系統會從當前Condition物件的等待佇列中,喚醒一個執行緒。一旦執行緒被喚醒,它會重新嘗試獲得與之繫結的重入鎖,一旦成功獲取,就可以繼續執行了。因此,在signal方法呼叫之後,一般需要釋放相關的鎖,謙讓給被喚醒的執行緒,讓他可以繼續執行。
private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); public void method1(){ try { lock.lock(); //釋放鎖,類似於 Object wait,阻塞於此 condition.await(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void method2(){ try { lock.lock(); //不釋放鎖類,似於Object notify condition.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } }