Lock接口獲取鎖的四個方法lock,tryLock,lockInterruptibly實例

原文鏈接:https://blog.csdn.net/qichangjian/java/article/details/88122419

Lock接口獲取鎖的四個方法lock,tryLock,lockInterruptibly實例

Lock和synchronized的比較?

Lock提供了比synchronized更多的功能。但是要注意以下幾點:

1)Lock不是Java語言內置的,synchronized是Java語言的關鍵字,因此是內置特性。Lock是一個類,通過這個類可以實現同步訪問;

2)Lock和synchronized有一點非常大的不同,采用synchronized不需要用戶去手動釋放鎖,當synchronized方法或者synchronized代碼塊執(zhí)行完之后,系統(tǒng)會自動讓線程釋放對鎖的占用;而Lock則必須要用戶去手動釋放鎖,如果沒有主動釋放鎖,就有可能導致出現死鎖現象。

Lock接口

首先要說明的就是Lock,通過查看Lock的源碼可知,Lock是一個接口:

public interface Lock {

void lock();//阻塞方法 ??阻塞的時間:另外一個線程釋放鎖

void lockInterruptibly() throws InterruptedException;//使鎖具備可被中斷的能力,防止死等,中斷在等待中的鎖

boolean tryLock();//非阻塞方法,試圖獲取鎖的方法 (線程啟動的時候 ?會嘗試的獲取鎖 ?獲取到---true ?獲取不到--false)

boolean tryLock(long time, TimeUnit unit) throws InterruptedException;//試圖獲取鎖的方法 (參數1:參數時間大小, 參數2:時間單位)

//阻塞方法 阻塞的時間就是參數的時間

//參數的時間內 ?獲取到了---true ?獲取不到---false

????void unlock();

????Condition newCondition();

}

下面來逐個講述Lock接口中每個方法的使用,?lock()、tryLock()、tryLock(long time, TimeUnit unit)和lockInterruptibly()?是用來獲取鎖的。unLock()方法是用來釋放鎖的

四種實現詳解

在Lock中聲明了四個方法來獲取鎖,那么這四個方法有何區(qū)別呢?


1.lock()

首先lock()方法是平常使用得最多的一個方法,就是用來獲取鎖。如果鎖已被其他線程獲取,則進行等待。


由于在前面講到如果采用Lock,必須主動去釋放鎖,并且在發(fā)生異常時,不會自動釋放鎖。因此一般來說,使用Lock必須在try{}catch{}塊中進行,并且將釋放鎖的操作放在finally塊中進行,以保證鎖一定被被釋放,防止死鎖的發(fā)生。通常使用Lock來進行同步的話,是以下面這種形式去使用的:

Lock lock = new ReentrantLock();

lock.lock();

try{

????//處理任務

}catch(Exception ex){


}finally{

????lock.unlock(); ??//釋放鎖

}

2.tryLock()

tryLock()方法是有返回值的,它表示用來嘗試獲取鎖,如果獲取成功,則返回true,如果獲取失?。存i已被其他線程獲取),則返回false,也就說這個方法無論如何都會立即返回。在拿不到鎖時不會一直在那等待。


3.tryLock(long time, TimeUnit unit)

tryLock(long time, TimeUnit unit)方法和tryLock()方法是類似的,只不過區(qū)別在于這個方法在拿不到鎖時會等待一定的時間,在時間期限之內如果還拿不到鎖,就返回false。如果如果一開始拿到鎖或者在等待期間內拿到了鎖,則返回true。


所以,一般情況下通過tryLock來獲取鎖時是這樣使用的:

Lock lock = ...;

if(lock.tryLock()) {

?????try{

?????????//處理任務

?????}catch(Exception ex){


?????}finally{

?????????lock.unlock(); ??//釋放鎖

?????}

}else {

????//如果不能獲取鎖,則直接做其他事情

}

4.lockInterruptibly()

lockInterruptibly()方法比較特殊,當通過這個方法去獲取鎖時,如果線程正在等待獲取鎖,則這個線程能夠響應中斷,即中斷線程的等待狀態(tài)。也就使說,當兩個線程同時通過lock.lockInterruptibly()想獲取某個鎖時,假若此時線程A獲取到了鎖,而線程B只有在等待,那么對線程B調用**threadB.interrupt()**方法能夠中斷線程B的等待過程。


由于lockInterruptibly()的聲明中拋出了異常,所以lock.lockInterruptibly()必須放在try塊中或者在調用lockInterruptibly()的方法外聲明拋出InterruptedException。


因此lockInterruptibly()一般的使用形式如下:

public void method() throws InterruptedException {

????lock.lockInterruptibly();

????try { ?

?????//.....

????}

????finally {

????????lock.unlock();

????} ?

}

注意,當一個線程獲取了鎖之后,是不會被interrupt()方法中斷的。因為本身在前面的文章中講過單獨調用interrupt()方法不能中斷正在運行過程中的線程,只能中斷阻塞過程中的線程。


因此當通過lockInterruptibly()方法獲取某個鎖時,如果不能獲取到,只有進行等待的情況下,是可以響應中斷的。


而用synchronized修飾的話,當一個線程處于等待某個鎖的狀態(tài),是無法被中斷的,只有一直等待下去。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容