對于RreentrantLock源碼的一些理解

該文只是作為個人對于占小狼關(guān)于深入淺出java同步器AQS文的自己一些補充,建議先看他的文章之后再來看該文。有理解不對的地方望提出來共同學(xué)習(xí)。

AQS實現(xiàn)原理是通過子類重寫tryAcquire和tryRelease方法通過CAS指令修改狀態(tài)變量state。(接下來我們會將AbstractQueuedSynchronizer簡寫成AQS方便書寫)

public final void acquire(int arg) {   
 if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))    
    selfInterrupt();
}

而我這里想解釋下RreentrantLock內(nèi)部對于tryAcquire()以及tryRelease()的一些自己理解。
對于RreentrantLock主要內(nèi)部是通過構(gòu)造的時候,判斷內(nèi)部使用公平鎖還是非公平鎖從而導(dǎo)致使用的時候有一些差異。

public ReentrantLock() {
        sync = new NonfairSync();
 }
public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
 }

這里公平鎖FairSync和NonfairSync都是繼承自Sync,我們先看下Sync。

abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;

        /**
         * Performs {@link Lock#lock}. The main reason for subclassing
         * is to allow fast path for nonfair version.
         */
        //lock是由我們的子類來實現(xiàn)
        abstract void lock();

        /**
         * Performs non-fair tryLock.  tryAcquire is implemented in
         * subclasses, but both need nonfair try for trylock method.
         */
        //他默認實現(xiàn)了非公平鎖的Acquire, 通過isLocked方法我們可以知道,state為0的時候為未上鎖狀態(tài),而非0則為上鎖狀態(tài)
        final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            //如果沒有上鎖,直接通過CAS修改state,如果修改成功,則說明請求鎖成功,將exclusiveOwnerThread設(shè)置為當前線程,這個屬性實際是AQS父類AbstractOwnableSynchronizer內(nèi)的屬性,實際就是為了記錄當前線程
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            //這里如果已經(jīng)上鎖了,則判斷當前上鎖的線程是否為當前線程,是的話繼續(xù)操作,否則直接返回false
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

   
        protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

        protected final boolean isHeldExclusively() {
            // While we must in general read state before owner,
            // we don't need to do so to check if current thread is owner
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        final ConditionObject newCondition() {
            return new ConditionObject();
        }

        // Methods relayed from outer class

        final Thread getOwner() {
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }

        final int getHoldCount() {
            return isHeldExclusively() ? getState() : 0;
        }

        final boolean isLocked() {
            return getState() != 0;
        }

        /**
         * Reconstitutes the instance from a stream (that is, deserializes it).
         */
        private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0); // reset to unlocked state
        }
    }

接下來看下非公平鎖:

static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * Performs lock.  Try immediate barge, backing up to normal
         * acquire on failure.
         */
        //非公平鎖會直接去設(shè)置state,如果當前state=0則直接相當于獲得鎖,否則就調(diào)用了AQS的acquire(1)
        //我理解非公平鎖不公平的原因在于比如現(xiàn)在AQS的等待隊列有兩個在等待獲得鎖的線程,當前獲得鎖的線程釋放了鎖,而這時候我們使用NonfairSync調(diào)用lock
        //的時候,不需要看等待隊列是否有等待獲得鎖的線程,而是直接和等待隊列的下一個獲得鎖的線程競爭鎖,如果競爭成功了,從而直接獲得了該鎖,導(dǎo)致
        //等待隊列中應(yīng)該獲得鎖的線程繼續(xù)等待,從而導(dǎo)致了不公平性。
        final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

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

接下來再看下公平鎖:

static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

        //根據(jù)上面的分析,這里直接調(diào)用AQS的acquire,如果沒有獲得鎖則直接加入到AQS的等待鎖的線程隊列,從而下次有鎖釋放直接從隊列第一位獲得鎖,保證了公平性
        final void lock() {
            acquire(1);
        }

        /**
         * Fair version of tryAcquire.  Don't grant access unless
         * recursive call or no waiters or is first.
         */
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                //判斷是否等待隊列中還有在等待的線程,這個代碼我單獨拿出來說明下
                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;
        }
    }

AQS的hasQueuedPredecessors:

public final boolean hasQueuedPredecessors() {
        // The correctness of this depends on head being initialized
        // before tail and on head.next being accurate if the current
        // thread is first in queue.
        //尾節(jié)點
        Node t = tail; // Read fields in reverse initialization order
        //頭節(jié)點
        Node h = head;
        Node s;
        //如果尾節(jié)點==頭節(jié)點的時候,這個時候我們認為等待隊列沒有在等待的線程
        //如果頭節(jié)點!=尾節(jié)點但是頭節(jié)點head.next == null,那么這種情況可能是這個時候正好被鎖的線程釋放鎖,并且等待隊列只有一個等待,直接變?yōu)榱薶ead從而head.next變?yōu)榭?,所以說明肯定是有前一個要獲得鎖或者等待鎖的節(jié)點
        return h != t &&
            ((s = h.next) == null || s.thread != Thread.currentThread());
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容