JUC代码浅析[3]——基于AQS的锁ReentrantReadWriteLock

JUC 代码浅析 [3] ——基于 AQS 的锁 ReentrantReadWriteLock

       ReentrantReadWriteLock 也是基于 AQS 实现的锁,它的特点是一个资源能够被多个读线程访问,或者被一个写线程访问,读和写是互斥的,可以同时有多个读但只能有一个写,大量读操作的场景下性能较好。 ReentrantReadWriteLock 并没有实现 Lock 接口,而是内部实现了 ReadLock WriteLock 分别针对读和写操作。看起来像两个锁,但其实这两个锁只是进行了一层适配,它们的主体都是 Sync ReadLock WriteLock 分别使用 Sync 的共享和独占模式。

 

ReadLock 加锁和释放,就是向 sync 请求共享模式进入和释放

        public void lock () {

            sync.acquireShared(1);

        }

        public   void unlock () {

            sync.releaseShared(1);

        }

 

WriteLock 加锁和释放,就是向 sync 请求互斥模式进入和释放

public void lock() {

            sync.acquire (1);

        }

public void unlock () {

            sync.release(1);

        }

 

       sync 的实现有公平和非公平两种 ( 下面介绍区别 ) sync 使用 int 的低 16 位表示写计数,高 16 位表示读计数,所以读锁和写锁的最高重入次数为 65535 ,超出将抛出 Error

获取写锁的实现片段,逻辑是:

l  如果读计数不为 0 ,失败;

l  如果写计数不为 0 并且不是当前线程持有锁,失败

l  如果写计数超出 65535 ,失败,抛出 Error

l  如果写计数为 0 并且当前线程需要阻塞,或者 state 被其他线程改变了,失败

l  以上条件都不满足则当前线程拥有写锁

protected final boolean tryAcquire ( int acquires) {

 

            Thread current = Thread.currentThread();

            int c = getState();

            int w = exclusiveCount(c);

            if (c != 0) {

                // (Note: if c != 0 and w == 0 then shared count != 0)

                if (w == 0 || current != getExclusiveOwnerThread())

                    return false ;

                if (w + exclusiveCount(acquires) > MAX_COUNT)

                    throw new Error( “Maximum lock count exceeded” );

            }

            if ((w == 0 && writerShouldBlock(current)) ||

                !compareAndSetState(c, c + acquires))

                return false ;

            setExclusiveOwnerThread(current);

            return true ;

        }

 

       非公平 sync 的写线程在总是不需要阻塞

        final boolean writerShouldBlock (Thread current) {

            return false ; // writers can always barge

        }

 

       公平 sync 的写线程只要 AQS 队列不为空并且不在第一个位置的就需要阻塞

        final boolean writerShouldBlock(Thread current) {

            // only proceed if queue is empty or current thread at head

            return !isFirst(current);

        }

 

 

       写锁的释放,减去并检查 state 计数,为 0 则表示写锁已经可以释放了,不为 0 说明该线程重入了写锁并把剩余的计数写入 state

        protected final boolean tryRelease ( int releases) {

            int nextc = getState() – releases;

            if (Thread.currentThread() != getExclusiveOwnerThread())

                throw new IllegalMonitorStateException();

            if (exclusiveCount(nextc) == 0) {

                setExclusiveOwnerThread( null );

                setState(nextc);

                return true ;

            } else {

                setState(nextc);

                return false ;

            }

        }

 

读锁的获取,

1 如果已经有线程获得写锁,并且不是当前线程获得的,失败

2 如果重入的读计数超出 65535 ,失败,抛出 Error

3 否则如果线程不用阻塞,并且增加读计数成功,则成功获得读锁

4 如果第三步失败(可能由于线程需要阻塞或者 CAS 修改失败),   不断尝试去修改状态直到成功或者锁被写入线程占有(看 fullTryAcquireShared 的实现 )

        protected final int tryAcquireShared ( int unused) {

            Thread current = Thread.currentThread();

            int c = getState();

            if (exclusiveCount(c) != 0 &&

                getExclusiveOwnerThread() != current)

                return -1;

            if (sharedCount(c) == MAX_COUNT)

                throw new Error( “Maximum lock count exceeded” );

            if (!readerShouldBlock(current) &&

                compareAndSetState(c, c + SHARED_UNIT)) {

                HoldCounter rh = cachedHoldCounter;

                 if (rh == null || rh.tid != current.getId())

                    cachedHoldCounter = rh = readHolds.get();

                rh.count++;

                return 1;

            }

            return fullTryAcquireShared(current);

    }

 

final int fullTryAcquireShared(Thread current) {

            HoldCounter rh = cachedHoldCounter;

            if (rh == null || rh.tid != current.getId())

                rh = readHolds.get();

            for (;;) {

                int c = getState();

                int w = exclusiveCount(c);

                if ((w != 0 && getExclusiveOwnerThread() != current) ||

                    ((rh.count | w) == 0 && readerShouldBlock(current)))

                    return -1;

                if (sharedCount(c) == MAX_COUNT)

                    throw new Error( “Maximum lock count exceeded”

    原文作者:JUC
    原文地址: https://blog.csdn.net/iteye_3559/article/details/82044982
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞