1. 程式人生 > 實用技巧 >Lock介面

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 執行緒同時保持,而寫入鎖是獨佔的。