併發程式設計 — Lock 介面說明
阿新 • • 發佈:2020-12-29
一、概述
在Java1.5版本以前,我們開發多執行緒程式只能通過關鍵字synchronized進行共享資源的同步、臨界值的控制,雖然隨著版本的不斷升級,JDK對synchronized關鍵字的效能優化工作一直都沒有停止過,但是synchronized在使用的過程中還是存在著比較多的缺陷和不足,比如:等待synchronized 鎖的執行緒無法被中斷,無法設定超時時間,無法獲取當前有多少執行緒被阻塞。在JDK 1.5 版本以後引入了 Lock 顯示鎖,Lock 鎖不但具備 synchronized 關鍵字提供的所有功能外,還解決了 synchronized 鎖存在的問題。
二、Lock 介面簡介
Lock 介面是對鎖操作方法的一個基本定義,它提供了 synchronized 關鍵字所具備的全部功能方法,另外我們可以藉助於Lock建立不同的Condition物件進行多執行緒間的通訊操作,與關鍵字synchronized進行方法同步程式碼塊同步的方式不同,Lock提供了程式設計式的鎖獲取(lock())以及釋放操作(unlock())等其他操作。Lock 中的介面如下所示:
public interface Lock {
/**
* 嘗試獲取鎖,
* 如果此刻該鎖未被其他執行緒持有,則會立即返回,並且設定鎖的hold計數為1;
* 如果當前執行緒已經持有該鎖則會再次嘗試申請,hold計數將會增加一個,並且立即返回;
* 如果該鎖當前被另外一個執行緒持有,那麼當前執行緒會進入阻塞,直到獲取該鎖,
* 由於呼叫lock方法而進入阻塞狀態的執行緒同樣不會被中斷,這一點與進入synchronized同步方法或者程式碼塊被阻塞類似
*/
void lock();
/**
* 該方法的作用與前者類似,但是使用該方法試圖獲取鎖而進入阻塞操作的執行緒則是可被中斷的,也就說執行緒可以獲得中斷訊號
*
* 如果鎖未被佔用,並且當前執行緒獲取到了鎖,則會立即返回.
* 如果鎖已被佔用,當前執行緒則會進入休眠,直到以下中的某一種情況發生:
* 1、當前執行緒申請到了鎖。
* 2、其他執行緒中斷了當前執行緒,並且支援鎖中斷
*/
void lockInterruptibly() throws InterruptedException;
/**
* 呼叫該方法獲取鎖,無論成功與否都會立即返回,執行緒不會進入阻塞狀態,
* 若成功獲取鎖則返回true,若獲取鎖失敗則返回false。
* 使用該方法時請務必注意進行結果的判斷,否則會出現獲取鎖失敗卻仍舊操作共享資源而導致資料不一致等問題的出現。
*/
boolean tryLock();
/**
* 該方法與tryLock()方法類似,只不過多了單位時間設定,
* 如果在單位時間內未獲取到鎖,則返回結果為false,
* 如果在單位時間內獲取到了鎖,則返回結果為true,同樣hold計數也會被設定為1。
*/
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
/**
* 當某個執行緒對鎖的使用結束之後,應該確保對鎖資源的釋放,
* 以便其他執行緒能夠繼續爭搶,unlock()方法的作用正在於此。
*/
void unlock();
/**
* 建立一個與該lock相關聯的Condition物件。
*/
Condition newCondition();
}
三、實現類
Lock的實現類如下所示:
Lock 介面的實現類中主要的就是 重入鎖 ReentrantLock 和 讀寫鎖 Readlock、WriteLock。
四、使用鎖的示例
Lock鎖又稱為 顯示鎖,在使用時需要手動的獲取鎖和釋放鎖,Lock鎖的使用正規化 如下所示:
//定義一個鎖
Lock lock = ...
//獲取鎖
lock.lock();
try{
}finally {
// 在finally 中釋放鎖
lock.unlock();
}
五、Lock 與 synchronized 的比較
- Lock是一個介面,是JDK層面的實現;而synchronized是Java中的關鍵字,是Java的內建特性,是JVM層面的實現;
- synchronized 在發生異常時,會自動釋放執行緒佔有的鎖,因此不會導致死鎖現象發生;而Lock在發生異常時,如果沒有主動通過unLock()去釋放鎖,則很可能造成死鎖現象,因此使用Lock時需要在finally塊中釋放鎖;
- Lock 可以讓等待鎖的執行緒響應中斷,而使用synchronized時,等待的執行緒會一直等待下去,不能夠響應中斷;
通過Lock可以知道有沒有成功獲取鎖,而synchronized卻無法辦到; - Lock 可用設定獲取鎖的超時時間,在指定時間內未獲取到鎖則返回,而 synchronized 無法做到, synchronized 獲取不到鎖,執行緒則會一直死等。
- Lock可以提高多個執行緒進行讀操作的效率。
在效能上來說,如果競爭資源不激烈,兩者的效能是差不多的。而當競爭資源非常激烈時(即有大量執行緒同時競爭),此時Lock的效能要遠遠優於synchronized。所以說,在具體使用時要根據適當情況選擇。