引:读写分离是解决并发瓶颈的常用策略,在Java中也有其实现——ReentrantReadWriteLock,它能够有效的提高读比写多的场景下的程序性能。
概览
ReentrantReadWriteLock是通过两把锁实现读写分离的,分别是读锁和写锁。它的源码如下:1
2
3
4
5
6
7
8public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {
// 读锁
private final ReentrantReadWriteLock.ReadLock readerLock;
// 写锁
private final ReentrantReadWriteLock.WriteLock writerLock;
// 同步器
final Sync sync;
写锁
写锁主要是通过重写同步器的tryAcquire和tryRelease实现,其他逻辑都可以参考AQS的解析。
tryAcquire
1 | // Sync |
tryRelease
1 | protected final boolean tryRelease(int releases) { |
读锁
写锁主要是通过重写同步器的tryAcquireShared和tryReleaseShared实现,其他逻辑都可以参考AQS的解析。
tryAcquireShared
1 | // Sync |
锁降级
在tryAcquireShared还体现了锁降级的概念。概念如下:
重入还允许从写入锁降级为读取锁,其实现方式是:先获取写入锁,然后获取读取锁,最后释放写入锁。但是,从读取锁升级到写入锁是不可能的。
体现在代码中如下:1
2
3
4// tryAcquireShared 或者 fullTryAcquireShared中
if (exclusiveCount(c) != 0) {
if (getExclusiveOwnerThread() != current)
return -1;
上面的代码就体现出:当写锁被持有的时候,如果当前是线程是持有写锁的那个线程,可以继续获得读锁。
总得来说就提高了性能。
tryReleaseShared
1 | // 当前线程重入次数计数器 |
总结
关于读写锁,它其实就是一个读锁一个写锁,读锁是共享的,写锁是独占的。然后我们再理解锁降级的相关概念就行了,当然这一切都是需要建立在读AQS的理解之上。