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

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

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

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

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

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

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

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

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

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"

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值