天天看點

可重入鎖和不可重入鎖的差別

大家好,又見面了,我是你們的朋友全棧君。

不可重入鎖示例(

同一個線程不可以重入上鎖後的代碼段

)

如下是一個不可重入鎖的邏輯過程,會發現執行main方法控制台會列印

執行doJob方法前

,然後就會一直線程阻塞,不會列印

執行doJob方法過程中

,原因在于第一次上鎖後,由于沒有釋放鎖,是以執行第一次lock後

isLocked = true

,這個時候調用

doJob()

内部又一次調用了

lock()

由于上個線程将

isLocked = true

,導緻再次進入的時候就進入死循環。導緻線程無法執行

System.out.println("執行doJob方法過程中");

這行代碼,是以控制台隻能列印

執行doJob方法前

。這種現象就造成了不可重入鎖

public class Count{ 
   
    MyLock lock = new MyLock();

    public static void main(String[] args) throws InterruptedException { 
   
        new Count().doSomeThing(); // 示例的main方法
    }
    public void doSomeThing() throws InterruptedException { 
   
        lock.lock(); // 第一次上鎖
        System.out.println("執行doJob方法前");
        doJob(); // 方法内會再次上鎖
        lock.unlock(); // 釋放第一次上的鎖
    }
    public void doJob() throws InterruptedException { 
   
        lock.lock();
        System.out.println("執行doJob方法過程中");
        lock.unlock();
    }
}

/** * 自定義鎖 */
class MyLock{ 
   
    private boolean isLocked = false;
    public synchronized void lock() throws InterruptedException{ 
   
        while(isLocked){ 
   
            wait();
        }
        isLocked = true; // 線程第一次進入後就會将器設定為true,第二次進入是就會由于where true進入死循環
    }
    public synchronized void unlock(){ 
   
        isLocked = false;   // 将這個值設定為false目的是釋放鎖
        notify();           // 接觸阻塞
    }
}           

複制

可重入鎖示例(

同一個線程可以重入上鎖的代碼段,不同的線程則需要進行阻塞

)

java的可重入鎖有:

ReentrantLock(顯式的可重入鎖)

synchronized(隐式的可重入鎖)

可重入鎖誕生的目的就是防止上面不可重入鎖的那種情況,導緻同一個線程不可重入上鎖代碼段。

目的就是讓同一個線程可以重新進入上鎖代碼段。

設計可重入鎖的示例代碼

public class MyReentrantLock { 
   
    boolean isLocked = false;   // 預設沒有上鎖
    Thread lockedBy = null; // 記錄阻塞線程
    int lockedCount = 0;    // 上鎖次數計數

    /** * 上鎖邏輯 */
    public synchronized void lock() throws InterruptedException { 
   
        Thread thread = Thread.currentThread();
        // 上鎖了 并且 如果是同一個線程則放行,否則其它線程需要進入where循環進行等待
        while (isLocked && lockedBy != thread) { 
    
            wait();
        }
        isLocked = true; // 第一次進入就進行上鎖
        lockedCount++; // 上鎖次數計數
        lockedBy = thread; // 目前阻塞的線程
    }

    /** * 釋放鎖邏輯 */
    public synchronized void unlock() { 
   
        if (Thread.currentThread() == this.lockedBy) { 
   
            lockedCount--; // 将上鎖次數減一
            if (lockedCount == 0) { 
   // 當計數為0,說明所有線程都釋放了鎖
                isLocked = false; // 真正的将釋放了所有鎖
                notify();
            }
        }
    }
}           

複制

釋出者:全棧程式員棧長,轉載請注明出處:https://javaforall.cn/153260.html原文連結:https://javaforall.cn