java源碼 - ReentrantReadWriteLock介紹

開(kāi)篇

?ReentrantReadWriteLock是Lock的另一種實(shí)現(xiàn)方式,我們已經(jīng)知道了ReentrantLock是一個(gè)排他鎖,同一時(shí)間只允許一個(gè)線程訪問(wèn),而ReentrantReadWriteLock允許多個(gè)讀線程同時(shí)訪問(wèn),但不允許寫(xiě)線程和讀線程、寫(xiě)線程和寫(xiě)線程同時(shí)訪問(wèn)。
?相對(duì)于排他鎖,提高了并發(fā)性。在實(shí)際應(yīng)用中,大部分情況下對(duì)共享數(shù)據(jù)(如緩存)的訪問(wèn)都是讀操作遠(yuǎn)多于寫(xiě)操作,這時(shí)ReentrantReadWriteLock能夠提供比排他鎖更好的并發(fā)性和吞吐量。
?這個(gè)系列主要是從源碼層面講解ReentrantReadWriteLock,總共分為3篇,歡迎訂閱。


ReentrantReadWriteLock類(lèi)

?ReentrantReadWriteLock類(lèi)包含三個(gè)核心變量:

  • readerLock:讀鎖。

  • writerLock:寫(xiě)鎖。

  • sync:可以為公平鎖FairSync 或 非公平鎖NonfairSync。

?ReentrantReadWriteLock類(lèi)的構(gòu)造函數(shù)執(zhí)行以下幾件事情:

  • 新建鎖對(duì)象賦予ReentrantReadWriteLock的sync對(duì)象。

  • 將ReentrantReadWriteLock對(duì)象作為this參數(shù)創(chuàng)建讀鎖ReadLock。

  • 將ReentrantReadWriteLock對(duì)象作為this參數(shù)創(chuàng)建寫(xiě)鎖WriteLock。

  • 在writerLock和ReadLock構(gòu)造函數(shù)中將ReentrantReadWriteLock的sync對(duì)象賦值為自身的sync對(duì)象,讀寫(xiě)鎖的操作其實(shí)用的就是ReentrantReadWriteLock的sync對(duì)象。

public class ReentrantReadWriteLock
        implements ReadWriteLock, java.io.Serializable {
    private static final long serialVersionUID = -6992448646407690164L;

    private final ReentrantReadWriteLock.ReadLock readerLock;

    private final ReentrantReadWriteLock.WriteLock writerLock;

    final Sync sync;

    public ReentrantReadWriteLock() {
        this(false);
    }

    public ReentrantReadWriteLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
        readerLock = new ReadLock(this);
        writerLock = new WriteLock(this);
    }

    public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
    public ReentrantReadWriteLock.ReadLock  readLock()  { return readerLock; }


ReadLock類(lèi)

  • ReadLock的構(gòu)造函數(shù)入?yún)镽eentrantReadWriteLock對(duì)象,通過(guò)將ReentrantReadWriteLock對(duì)象的sync對(duì)象賦值給ReadLock的Sync。
  • ReadLock的lock和unlock操作都通過(guò)sync對(duì)象來(lái)實(shí)現(xiàn)加鎖和解鎖
    public static class ReadLock implements Lock, java.io.Serializable {
        private static final long serialVersionUID = -5992448646407690164L;
        private final Sync sync;

        protected ReadLock(ReentrantReadWriteLock lock) {
            sync = lock.sync;
        }

        public void lock() {
            sync.acquireShared(1);
        }

        public void lockInterruptibly() throws InterruptedException {
            sync.acquireSharedInterruptibly(1);
        }

        public boolean tryLock() {
            return sync.tryReadLock();
        }

        public boolean tryLock(long timeout, TimeUnit unit)
                throws InterruptedException {
            return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
        }

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

        public Condition newCondition() {
            throw new UnsupportedOperationException();
        }
    }


WriteLock類(lèi)

  • WriteLock的構(gòu)造函數(shù)入?yún)镽eentrantReadWriteLock對(duì)象,通過(guò)將ReentrantReadWriteLock對(duì)象的sync對(duì)象賦值給ReadLock的Sync。
  • WriteLock的lock和unlock操作都通過(guò)sync對(duì)象來(lái)實(shí)現(xiàn)加鎖和解鎖
    public static class WriteLock implements Lock, java.io.Serializable {
        private static final long serialVersionUID = -4992448646407690164L;
        private final Sync sync;

        protected WriteLock(ReentrantReadWriteLock lock) {
            sync = lock.sync;
        }

        public void lock() {
            sync.acquire(1);
        }

        public void lockInterruptibly() throws InterruptedException {
            sync.acquireInterruptibly(1);
        }

        public boolean tryLock( ) {
            return sync.tryWriteLock();
        }

        public boolean tryLock(long timeout, TimeUnit unit)
                throws InterruptedException {
            return sync.tryAcquireNanos(1, unit.toNanos(timeout));
        }

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

        public Condition newCondition() {
            return sync.newCondition();
        }

        public boolean isHeldByCurrentThread() {
            return sync.isHeldExclusively();
        }

        public int getHoldCount() {
            return sync.getWriteHoldCount();
        }
    }


公平鎖和非公平鎖類(lèi)定義

  • 公平鎖FairSync和非公平鎖NonfairSync屬于ReentrantReadWriteLock內(nèi)部定義類(lèi),繼承自Sync類(lèi)。
  • Sync類(lèi)繼承自AbstractQueuedSynchronizer類(lèi),Sync類(lèi)有一些核心的變量已經(jīng)加注釋。
  • AQS的state變量32位分開(kāi)高16位為讀狀態(tài),低16位為寫(xiě)狀態(tài)。


    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = -8159625535654395037L;
        final boolean writerShouldBlock() {
            return false; // writers can always barge
        }
        final boolean readerShouldBlock() {
            return apparentlyFirstQueuedIsExclusive();
        }
    }

    static final class FairSync extends Sync {
        private static final long serialVersionUID = -2274990926593161451L;
        final boolean writerShouldBlock() {
            return hasQueuedPredecessors();
        }
        final boolean readerShouldBlock() {
            return hasQueuedPredecessors();
        }
    }

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

        static final int SHARED_SHIFT   = 16;
        // 高16位記錄讀狀態(tài)
        static final int SHARED_UNIT    = (1 << SHARED_SHIFT);
        static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;
        // 低16位記錄寫(xiě)狀態(tài)
        static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

        static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }
        static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }

        static final class HoldCounter {
            int count = 0;
            // Use id, not reference, to avoid garbage retention
            final long tid = getThreadId(Thread.currentThread());
        }

        static final class ThreadLocalHoldCounter
            extends ThreadLocal<HoldCounter> {
            public HoldCounter initialValue() {
                return new HoldCounter();
            }
        }

        private transient ThreadLocalHoldCounter readHolds;
        private transient HoldCounter cachedHoldCounter;
        private transient Thread firstReader = null;
        private transient int firstReaderHoldCount;

        Sync() {
            readHolds = new ThreadLocalHoldCounter();
            setState(getState()); // ensures visibility of readHolds
        }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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