jdk1.8 J.U.C并发源码阅读------ReentrantReadWriteLock源码解析

一、继承关系

public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable
实现了ReadWriteLock接口和Serializable接口
ReadWriteLock接口内部包含两个抽象方法:

Lock readLock();//返回一个读锁(共享锁)
Lock writeLock();//返回一个写锁(独占锁)
说明:
(1)ReentrantReadWriteLock中包含了读锁和写锁,分别有公平和非公平两种实现。
(2)该类中包含一个继承了AQS的Sync类型的对象,Sync抽象类有两个子类NonfairSync和FairSync,分别实现公平和非公平两种方式。在new ReentrantReadWriteLock对象时可以传递一个boolean类型的参数指定是读写锁是采用公平还是非公平策略实现。
(3)readLock和writeLock中都包含一个成员变量sync,lock和unlock都是通过调用sync对象的相应方法实现。

二、成员变量

/** Inner class providing readlock */
private final ReentrantReadWriteLock.ReadLock readerLock;//读锁
/** Inner class providing writelock */
private final ReentrantReadWriteLock.WriteLock writerLock;//写锁
/** Performs all synchronization mechanics */
final Sync sync;//AQS子类

三、内部类

(1)Sync:继承自AQS
总结:
写线程获取锁成功情况:
(1)有线程独占锁(可能该线程还共享的占有锁),且该线程是自身,这时写线程获取锁成功。
(2)没有线程占有锁,锁处于空闲状态,此时该写线程可能占有锁成功。
(3)当只有读线程占有锁(无论是否是自身),或者有线程独占锁但不是自身,这两种情况获取锁失败。
读线程获取锁成功情况:
(1)有写线程占有锁,但该写线程是自身,获取锁成功
(2)没有写线程占有锁,获取锁成功
(3)当有写线程占有锁,且不是自身时,获取锁失败。
关于锁降级:写锁--->读锁
当该线程的写线程占有锁,该线程又想以读方式占有锁,此时获取成功,该线程的分别以读和写的方式占有锁,若此时,该线程写方式释放了锁,则此时锁由写锁降级成了读锁。(顺序:写--读---写释放)

abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 6317671515068378041L;
		//由于AQS中state只有一个变量保存锁的数目,这里有两种锁的数目需要保存,故采用将state划分为高16位和低16位,高位保存共享锁的数目,低位保存独占锁的数目
        static final int SHARED_SHIFT   = 16;
        static final int SHARED_UNIT    = (1 << SHARED_SHIFT);//1左移16位为0x100,共享锁的最小单位
        static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;//共享锁和独占锁的最大数目为0xff
        static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;//独占锁的掩码

        /** Returns the number of shared holds represented in count  */
        static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }//右移16位,获取高位表示的共享锁的数目
        /** Returns the number of exclusive holds represented in count  */
        static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }//与0xff进行&操作,获得低位的独占锁的数目

        /**
         * A counter for per-thread read hold counts.
         * Maintained as a ThreadLocal; cached in cachedHoldCounter
         */
		 //每一个线程拥有锁的数目
        static final class HoldCounter {
            int count = 0;
            // Use id, not reference, to avoid garbage retention
            final long tid = getThreadId(Thread.currentThread());
        }

        /**
         * ThreadLocal subclass. Easiest to explicitly define for sake
         * of deserialization mechanics.
         */
		 //将holdCounter与Thread结合起来
        static final class ThreadLocalHoldCounter
            extends ThreadLocal<HoldCounter> {
            public HoldCounter initialValue() {
                return new HoldCounter();
            }
        }

        /**
         * The number of reentrant read locks held by current thread.
         * Initialized only in constructor and readObject.
         * Removed whenever a thread's read hold count drops to 0.
         */
        private transient ThreadLocalHoldCounter readHolds;

        /**
         * The hold count of the last thread to successfully acquire
         * readLock. This saves ThreadLocal lookup in the common case
         * where the next thread to release is the last one to
         * acquire. This is non-volatile since it is just used
         * as a heuristic, and would be great for threads to cache.
         *
         * <p>Can outlive the Thread for which it is caching the read
         *
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值