在Java的锁中很多锁都是同一时刻只允许一个线程访问,今天就来看看一个特殊的锁——读写锁。它的特殊之处就在于同一时刻可以运行多个读线程访问或者有一个写线程在访问。能够大大的提高并发性和吞吐量
ReentrantReadWriteLock介绍
读写锁是一种特殊的自旋锁。在读写锁的世界里,访问共享资源的线程被划分为两类:一类是只对共享资源进行访问而不更改,暂且认为他是读者;一类是改变共享资源,即写操作,是写者。这个锁的核心要求是在没有任何线程获得读锁和写锁的情况才能获得写锁。
ReentrantReadWriteLock特性
公平性:读写锁支持非公平和公平的锁获取方式,非公平锁的吞吐量优于公平锁的吞吐量,默认构造的是非公平锁
可重入:在线程获取读锁之后能够再次获取读锁,但是不能获取写锁,而线程在获取写锁之后能够再次获取写锁,同时也能获取读锁
锁降级:线程获取写锁之后获取读锁,再释放写锁,这样实现了写锁变为读锁,也叫锁降级
ReentrantReadWriteLock的内部类Sync核心源码解析
1、类的属性
1 abstract static class Sync extends AbstractQueuedSynchronizer { 2 // 版本序列号 3 private static final long serialVersionUID = 6317671515068378041L; 4 // 通过将整形变量state切成两部分,高16位表示读,低16位表示写,来区分读写状态。 5 static final int SHARED_SHIFT = 16; 6 7 static final int SHARED_UNIT = (1 << SHARED_SHIFT); 8 9 static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1; 10 11 static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1; 12 // 本地线程计数器 13 private transient ThreadLocalHoldCounter readHolds; 14 // 缓存的计数器 15 private transient HoldCounter cachedHoldCounter; 16 // 第一个读线程 17 private transient Thread firstReader = null; 18 // 第一个读线程的计数 19 private transient int firstReaderHoldCount; 20 }