一、简介
1.1 什么是读写锁
在日常开发的过程中,经常存在一种场景:对于某些共享资源有读和写的操作,但是读操作要比写操作频繁(读多写少的情况)。
在没有写操作的时候,对于读操作完全不需要考虑共享资源的安全问题(共享读),但有了写操作之后,为了保证读写的共享资源的数据一致性,就必须进行同步,即写写、写读、读写都是需要进行互斥的。如果我们直接使用ReentrantLock独占锁来解决读写共存的场景时,在高并发的情况下,性能就会受到很大影响,毕竟读读之间不需要进行互斥,于是就有了读写锁。
在读多写少的情况下,读写锁要比排他锁(独占锁)具有更好的并发性和吞吐量。
针对上面这种情况,Java的并发工具包提供了读写锁的实现ReentrantReadWriteLock
,在它内部,维护了一对相关的锁,用于只读操作的读锁,读锁由共享锁实现且支持重入;用于写操作的写锁,写锁由独占锁实现也支持重入。
线程可以获取读锁的前提条件:
- 没有其他线程已获取写锁
- 没有写请求或有写请求,但请求读锁的和持有写锁的线程是同一个
线程可以获取写锁的前提条件:
- 没有其他线程的读锁
- 没有其他线程的写锁
ReentrantReadWriteLock具有以下三个重要的特性:
- 公平选择性:支持非公平(默认)和公平两种获取锁的方式,同样非公平的方式性能更好一些
- 可重入:读锁和写锁都支持可重入。
- 锁降级:当线程获取写锁后,可以继续获取读锁,然后再释放写锁;按照这个次序就完成了从写锁到读锁的降级过程
1.2 读写锁类结构
ReentrantReadWriteLock
实现了ReadWriteLock
接口,该接口中提供了两个方法,分别可以获取读锁和写锁的Lock对象
public interface ReadWriteLock {
/**
* Returns the lock used for reading
*/
Lock readLock();
/**
* Returns the lock used for writing.
*/
Lock writeLock();
}
ReentrantReadWriteLock
的类结构如下:
内部维护了读锁和写锁,写锁是独占的,读锁是共享的
赞 (0)