1. 程式人生 > >java基礎總結(二十九)--Java不可重入鎖和可重入鎖理解

java基礎總結(二十九)--Java不可重入鎖和可重入鎖理解

來自:https://blog.csdn.net/u012545728/article/details/80843595

 

最近正在閱讀Java ReentrantLock原始碼,始終對可重入和不可重入概念理解不透徹,進行學習後記錄在這裡。

基礎知識
Java多執行緒的wait()方法和notify()方法

這兩個方法是成對出現和使用的,要執行這兩個方法,有一個前提就是,當前執行緒必須獲其物件的monitor(俗稱“鎖”),否則會丟擲IllegalMonitorStateException異常,所以這兩個方法必須在同步塊程式碼裡面呼叫。

wait():阻塞當前執行緒

notify():喚起被wait()阻塞的執行緒

不可重入鎖
所謂不可重入鎖,即若當前執行緒執行某個方法已經獲取了該鎖,那麼在方法中嘗試再次獲取鎖時,就會獲取不到被阻塞。我們嘗試設計一個不可重入鎖:

public class Lock{
    private boolean isLocked = false;
    public synchronized void lock() throws InterruptedException{
        while(isLocked){    
            wait();
        }
        isLocked = true;
    }
    public synchronized void unlock(){
        isLocked = false;
        notify();
    }
}

使用該鎖:

public class Count{
    Lock lock = new Lock();
    public void print(){
        lock.lock();
        doAdd();
        lock.unlock();
    }
    public void doAdd(){
        lock.lock();
        //do something
        lock.unlock();
    }
}

當前執行緒執行print()方法首先獲取lock,接下來執行doAdd()方法就無法執行doAdd()中的邏輯,必須先釋放鎖。這個例子很好的說明了不可重入鎖。

可重入鎖

接下來,我們設計一種可重入鎖

public class Lock{
    boolean isLocked = false;
    Thread  lockedBy = null;
    int lockedCount = 0;
    public synchronized void lock()
            throws InterruptedException{
        Thread thread = Thread.currentThread();
        while(isLocked && lockedBy != thread){
            wait();
        }
        isLocked = true;
        lockedCount++;
        lockedBy = thread;
    }
    public synchronized void unlock(){
        if(Thread.currentThread() == this.lockedBy){
            lockedCount--;
            if(lockedCount == 0){
                isLocked = false;
                notify();
            }
        }
    }
}

所謂可重入,意味著執行緒可以進入它已經擁有的鎖的同步程式碼塊兒。

我們設計兩個執行緒呼叫print()方法,第一個執行緒呼叫print()方法獲取鎖,進入lock()方法,由於初始lockedBy是null,所以不會進入while而掛起當前執行緒,而是是增量lockedCount並記錄lockBy為第一個執行緒。接著第一個執行緒進入doAdd()方法,由於同一程序,所以不會進入while而掛起,接著增量lockedCount,當第二個執行緒嘗試lock,由於isLocked=true,所以他不會獲取該鎖,直到第一個執行緒呼叫兩次unlock()將lockCount遞減為0,才將標記為isLocked設定為false。

可重入鎖的概念和設計思想大體如此,Java中的可重入鎖ReentrantLock設計思路也是這樣