ReentrantLock
重入鎖使用java.util.concurrent.locks.ReentrantLock類來實現(xiàn)。它的幾個重要方法如下:
lock():獲得鎖,如果鎖已經(jīng)被占用,則等待。
lockInterruptibly():獲得鎖,但優(yōu)先響應(yīng)中斷。
tryLock():嘗試獲得鎖,如果成功,返回true,失敗返回false。該方法不等待,立即返回。
tryLock(long time, TimeUnit unit):在給定時間內(nèi)嘗試獲得鎖。 unLock():釋放鎖。
對于重入鎖,同一個線程可以多次獲得鎖,但是釋放鎖的時候,也必須釋放相同次數(shù)。否則會產(chǎn)生異常。
Condition條件
通過Condition的newCondition()方法可以生成一個與當前重入鎖綁定的Condition實例。利用Condition對象,我們就可以讓線程在合適的時間等待,或者在某一個特定的時間得到通知,繼續(xù)執(zhí)行。
await() 方法會是當前線程等待,同時釋放當前鎖,當其他線程中使用signal() 或signalAll() 方法時,線程會重新獲得鎖并繼續(xù)執(zhí)行?;蛘弋斁€程被中斷時,也能跳出等待;signal() 方法用于喚醒一個在等待中的線程。
當線程使用Condition.await時,要求線程持有相關(guān)的重入鎖,在Condition.await調(diào)用后,這個線程會釋放這把鎖。同理,在Condition.signal方法調(diào)用時,也要求線程先獲得相關(guān)的鎖。在signal方法調(diào)用后,系統(tǒng)會從當前Condition對象的等待隊列中,喚醒一個線程。一旦線程被喚醒,它會重新嘗試獲得與之綁定的重入鎖,一旦成功獲取,就可以繼續(xù)執(zhí)行了。因此,在signal方法調(diào)用之后,一般需要釋放相關(guān)的鎖,謙讓給被喚醒的線程,讓他可以繼續(xù)執(zhí)行。
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();
}
}