天天看點

【java并發程式設計】Lock接口

​ JDK1.5開始引入顯式鎖,

Lock

與使用

synchronized

方法和語句相比,實作提供了更廣泛的鎖定操作。它們允許更靈活的結構,可以具有完全不同的屬性。

1.接口說明

Modifier and Type Method and Description

void

lock()

Acquires the lock.(擷取鎖)

void

lockInterruptibly()

Acquires the lock unless the current thread is interrupted.(擷取鎖,除非目前線程被中斷。)

Condition

newCondition()

Returns a new

Condition

instance that is bound to this

Lock

instance.(傳回一個Condition執行個體,java條件變量)

boolean

tryLock()

Acquires the lock only if it is free at the time of invocation.(嘗試擷取鎖)

boolean

tryLock(long time, TimeUnit unit)

Acquires the lock if it is free within the given waiting time and the current thread has not been interrupted.(嘗試擷取鎖,超市中斷)

void

unlock()

Releases the lock.(釋放鎖)

2.基本使用

public static void main(String[] args) {
        Lock lock = new ReentrantLock();
        //申請鎖
        lock.lock();
        try {
            //todo 業務邏輯
        }finally {
            // unlock放到finally塊中,避免鎖洩露
            lock.unlock();
        }
    }
           
  • lock/unlock是成對使用的,unlock要放到finally中,避免鎖洩露
  • ReentrantLock是可重入鎖,new ReentrantLock(boolean fair)當fair為true表示公平鎖,因為公平鎖使用開銷比非公平鎖打,是以預設為非公平鎖政策。

3.Lock和synchronized對比

  1. synchronized比較死闆,在申請鎖時隻能等待,不能中斷,不能跨越方法塊,Lock相對靈活,有tryLock()方法,這樣就有了等待逾時,而且可以在一個方法中申請,另一個方法中釋放,比較靈活。
  2. synchronized不容易有鎖洩露,在使用Lock的時候稍微不注意就會造成鎖洩露。切記lock/unlock要成對出現,unlock要放到finally中。
  3. synchronized具有可重入性,但是非公平,Lock同樣具有重入性,但是也有公平鎖。
  4. ReentrantLock還有很多方法
    1. isLocked()方法用于檢測鎖是否被某個線程持有。
    2. getQueueLength()方法檢測等待線程的數量。
    3. hasQueuedThreads()是否有線程等待
    4. hasQueuedThread(Thread thread)目前線程是否在等待
    5. isFair()是否是公平鎖,傳回true則為公平鎖
    6. 等等詳細到->官網位址

4.讀寫鎖

4.1定義

​ 鎖的排他性使得多個線程無法以安全的方式在同一時間對共享變量的進行讀取(僅僅讀取),這個不利于提高系統的并發性。

​ 讀寫鎖是一種改型的排它鎖。

  • 它允許多個線程同時讀取(隻讀)共享變量,但是隻允許一個線程對線程的共享變量進行更新(包括讀取更新)。
  • 任何線程讀取共享變量的時候,其他線程無法更新變量。
  • 一個線程更新變量的時候,其他線程無法通路變量。
  • 讀鎖是共享的,可以有多個線程一起持有;寫鎖是排他的,一個線程擷取寫鎖之後,其他線程無法再次擷取寫鎖和讀鎖。

4.2代碼實作

public static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    public static final Lock read = lock.readLock();
    public static final Lock write = lock.writeLock();
    public static void main(String[] args) {
        // 讀鎖
           read.lock();
           try{
            //todo
           }catch (Exception e){

           }finally {
               // 在finally中釋放,避免鎖洩露
               read.unlock();
           }


           // 寫鎖
        write.lock();
        try{
            //todo
        }catch (Exception e){

        }finally {
            // 在finally中釋放,避免鎖洩露
            write.unlock();
        }
    }
           

讀寫鎖和ReentrantLock邏輯類似,畢竟都是繼承了Lock接口,

4.3讀寫鎖降級