juc併發工具三-ReentrantLock

目錄

 

1 重入鎖概述

2 非公平鎖加鎖

3 公平鎖加鎖

4 釋放鎖

 5 公平鎖和非公平鎖比較


1 重入鎖概述

ReentrantLock加鎖解鎖就是AQS實現的Sync同步工具類
在ReentrantLock中,state如果等於0,表示資源空閒;如果>0表示資源被佔用,具體數值表示資源被佔用次數,即重入次數

2 非公平鎖加鎖

    final void lock() {
        if (compareAndSetState(0, 1))
            setExclusiveOwnerThread(Thread.currentThread());
        else
            acquire(1);
    }


    加鎖的時候不會直接獲取資源,而是再查看當前資源佔用狀態,如果沒有佔用則直接佔用,這是非公平的體現;否則才進行獲取資源過程
    上篇文章中已經分析了acquire方法的執行過程,現在看一下acquire方法中第一步tryAcquire在非公平鎖中的具體實現

    protected final boolean tryAcquire(int acquires) {
        return nonfairTryAcquire(acquires);
    }

    final boolean nonfairTryAcquire(int acquires) {
        final Thread current = Thread.currentThread();
        int c = getState();
        // 這裏再獲取一下state資源狀態,如果沒有被佔用則進行cas爭取
        if (c == 0) {
            if (compareAndSetState(0, acquires)) {
                setExclusiveOwnerThread(current);
                return true;
            }
        }
        else if (current == getExclusiveOwnerThread()) {
            // 如果當前線程就是被佔用線程則把state狀態+1
            int nextc = c + acquires;
            if (nextc < 0) // overflow
                // 這裏可以看到可重入鎖也不是可以無限重入,最大次數是Integer.MAX_VALUE;
                throw new Error("Maximum lock count exceeded");
            setState(nextc);
            return true;
        }
        return false;
    }

3 公平鎖加鎖

    final void lock() {
        acquire(1);
    }

可以看到與非公平鎖的區別是直接進行獲取資源,而不是先檢查當前資源狀態,這裏在看一下公平鎖中tryAcquire方法的實現

    protected final boolean tryAcquire(int acquires) {
        final Thread current = Thread.currentThread();
        int c = getState();
        if (c == 0) {
            // 當前state沒有資源佔用並且隊列中沒有等待的線程才進行cas搶鎖,確保公平性
            if (!hasQueuedPredecessors() &&
                compareAndSetState(0, acquires)) {
                setExclusiveOwnerThread(current);
                return true;
            }
        }
        // 這裏和非公平鎖一致
        else if (current == getExclusiveOwnerThread()) {
            int nextc = c + acquires;
            if (nextc < 0)
                throw new Error("Maximum lock count exceeded");
            setState(nextc);
            return true;
        }
        return false;
    }


4 釋放鎖

    public void unlock() {
        sync.release(1);
    }

上篇文章中已經分析了release方法執行過程,這裏看一下tryRelease方法在ReentrantLock中的具體實現

    protected final boolean tryRelease(int releases) {
        if (!isHeldExclusively())
            // 如果不是佔用資源的線程釋放鎖直接拋異常
            throw new IllegalMonitorStateException();
        // state狀態-releases
        int nextc = getState() - releases;
        boolean free = exclusiveCount(nextc) == 0;
        if (free)
            // 如果state==0表示沒有線程佔用資源,設置當前佔用線程爲空
            setExclusiveOwnerThread(null);
        setState(nextc);
        return free;
    }

 5 公平鎖和非公平鎖比較

  • 分析源碼可知公平鎖可以保證線程先到先執行,而非公平鎖不能
  •  非公平鎖性能高於公平鎖性能。

        首先非公平鎖更多次的執行CAS能更充分的利用cpu的時間片,儘量的減少cpu空閒的狀態時間,降低線程進入隊列等待執行的可能。

        其次在恢復一個被掛起的線程與該線程真正運行之間存在着嚴重的延遲。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章