Lock介面
Lock介面
Lock不是Java中的關鍵字而是java.util.concurrent.locks包中的一個介面。下面我們簡單介紹一下Lock介面。
一、Lock介面簡介
Lock
實現提供了比使用synchronized
方法和語句可獲得的更廣泛的鎖定操作。此實現允許更靈活的結構,可以具有差別很大的屬性,可以支援多個相關的Condition
物件。
Lock相對於synchronized關鍵字而言更加靈活,你可以自由得選擇我你想要加鎖的地方。當然更高的自由度也帶來更多的責任。
Lock介面有6個方法:
方法名稱 | 描述 |
void lock() | 獲取鎖,呼叫該方法當前執行緒將會獲取鎖,當鎖獲得後,從該方法返回 |
void lockInterruptibly() | 如果當前執行緒未被中斷,則獲取鎖,可以響應中斷 |
Condition newCondition() |
獲取等待通知元件,該元件和當前的鎖繫結,當前執行緒只有獲得了鎖,才能呼叫該元件的wait()方法,而呼叫後,當前執行緒將釋放鎖 |
boolean tryLock() |
僅在呼叫時鎖為空閒狀態才獲取該鎖,可以響應中斷 嘗試非阻塞的獲取鎖,呼叫該方法後立刻返回,如果能夠獲取則返回true,否則返回false |
boolean tryLock(long time, TimeUnit unit) |
超時的獲取鎖,當前執行緒在以下3種情況下會返回: 1當前執行緒在超時時間內獲得了鎖 2當前執行緒在超時時間內被中斷 3超時時間結束,返回false |
void unlock() | 釋放鎖 |
void lock() :獲取鎖
是平常使用得最多的一個方法,就是用來獲取鎖。如果鎖已被其他執行緒獲取,則進行等待。在前面已經講到,如果採用Lock,必須主動去釋放鎖,並且在發生異常時,不會自動釋放鎖
void lockInterruptibly() : 如果當前執行緒未被中斷,則獲取鎖,可以響應中斷
方法比較特殊,當通過這個方法去獲取鎖時,如果執行緒正在等待獲取鎖,則這個執行緒能夠響應中斷,即中斷執行緒的等待狀態。例如,當兩個執行緒同時通過lock.lockInterruptibly()想獲取某個鎖時,假若此時執行緒A獲取到了鎖,而執行緒B只有在等待,那麼對執行緒B呼叫threadB.interrupt()方法能夠中斷執行緒B的等待過程
Condition newCondition() :返回繫結到此 Lock 例項的新 Condition 例項
boolean tryLock() :僅在呼叫時鎖為空閒狀態才獲取該鎖,可以響應中斷
是有返回值的,它表示用來嘗試獲取鎖,如果獲取成功,則返回true;如果獲取失敗(即鎖已被其他執行緒獲取),則返回false,也就是說,這個方法無論如何都會立即返回(在拿不到鎖時不會一直在那等待)
boolean tryLock(long time, TimeUnit unit) :如果鎖在給定的等待時間內空閒,並且當前執行緒未被中斷,則獲取鎖
方法和tryLock()方法是類似的,只不過區別在於這個方法在拿不到鎖時會等待一定的時間,在時間期限之內如果還拿不到鎖,就返回false,同時可以響應中斷。如果一開始拿到鎖或者在等待期間內拿到了鎖,則返回true
void unlock() :釋放鎖
範程式碼
Lock lock = new ReentrantLock();
// 獲取鎖
lock.lock();
try {
// 訪問此鎖保護的資源
} finally {
// 釋放鎖
lock.unlock();
}
Lock的實現類 ReentrantLock
Lock介面有三個實現類分別是ReentrantLock,ReentrantReadWriteLock.ReadLock,ReentrantReadWriteLock.WriteLock。後面兩個是內部類。
ReentrantLock,即可重入鎖。ReentrantLock是唯一實現了Lock介面的類,並且ReentrantLock提供了更多的方法
第一個ReentrantLock,在我們平常使用中更為頻繁。
ReentrantLock是一個可重入的互斥鎖Lock
,它具有與使用synchronized
方法和語句所訪問的隱式監視器鎖相同的一些基本行為和語義,但功能更強大。
ReentrantLock的構造方法接受一個可選的公平引數。當設定為true
時,在多個執行緒的爭用下,這些鎖傾向於將訪問權授予等待時間最長的執行緒。否則此鎖將無法保證任何特定訪問順序。也就是說這裡可以設定鎖的型別為公平鎖還是非公平鎖。但是,需要注意的是公平鎖的情況下,也不能完全確保公平,它總是趨向公平的情況。
如:Lock lock = new ReentrantLock();
實列:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyLockText {
Lock lock = new ReentrantLock();
public void lock(String name) {
// 獲取鎖
lock.lock();
try {
System.out.println(name + " get the lock");
// 訪問此鎖保護的資源
} finally {
// 釋放鎖
lock.unlock();
System.out.println(name + " release the lock");
}
}
public static void main(String[] args) {
MyLockText lt = new MyLockText();
new Thread(() -> lt.lock("1234")).start();
new Thread(() -> lt.lock("5678")).start();
}
}
結果:
1234 get the lock
1234 release the lock
5678 get the lock
5678 release the lock
ReadWriteLock 介面只有兩個方法:
//返回用於讀取操作的鎖
Lock readLock()
//返回用於寫入操作的鎖
Lock writeLock()
ReadWriteLock 維護了一對相關的鎖,一個用於只讀操作,另一個用於寫入操作。只要沒有 writer,讀取鎖可以由多個 reader 執行緒同時保持,而寫入鎖是獨佔的。