资料内容:
1. 读写锁介绍
读写锁ReadWriteLock,顾名思义一把锁分为读与写两部分,读锁允许多个线程同时获得,因为读操
作本身是线程安全的。而写锁是互斥锁,不允许多个线程同时获得写锁。并且读与写操作也是互斥
的。读写锁适合多读少写的业务场景。
2. ReentrantReadWriteLock介绍
针对这种场景,JAVA的并发包提供了读写锁ReentrantReadWriteLock,它内部,维护了一对相
关的锁,一个用于只读操作,称为读锁;一个用于写入操作,称为写锁,描述如下:
线程进入读锁的前提条件:
没有其他线程的写锁
没有写请求或者有写请求,但调用线程和持有锁的线程是同一个。
线程进入写锁的前提条件:
没有其他线程的读锁
没有其他线程的写锁
而读写锁有以下三个重要的特性:
公平选择性:支持非公平(默认)和公平的锁获取方式,吞吐量还是非公平优于公平。
可重入:读锁和写锁都支持线程重入。以读写线程为例:读线程获取读锁后,能够再次获取读锁。写线程在获取写锁之后能够再次获取写锁,同时也可以获取读锁。
锁降级:遵循获取写锁、再获取读锁最后释放写锁的次序,写锁能够降级成为读锁。
2.1 ReentrantReadWriteLock的使用
读写锁接口ReadWriteLock
一对方法,分别获得读锁和写锁 Lock 对象。
ReentrantReadWriteLock类结构
ReentrantReadWriteLock是可重入的读写锁实现类。在它内部,维护了一对相关的锁,一个用于
只读操作,另一个用于写入操作。只要没有 Writer 线程,读锁可以由多个 Reader 线程同时持有。也
就是说,写锁是独占的,读锁是共享的。
如何使用读写锁
1 private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
2 private Lock r = readWriteLock.readLock();
3 private Lock w = readWriteLock.writeLock();
4
5 // 读操作上读锁
6 public Data get(String key) {
7 r.lock();
8 try {
9 // TODO 业务逻辑
10 }finally {
11 r.unlock();
12 }
13 }
14
15 // 写操作上写锁
16 public Data put(String key, Data value) {
17 w.lock();
18 try {
19 // TODO 业务逻辑
20 }finally {
21 w.unlock();
22 }
23 }
注意事项
读锁不支持条件变量
重入时升级不支持:持有读锁的情况下去获取写锁,会导致获取永久等待
重入时支持降级: 持有写锁的情况下可以去获取读锁
2.2 应用场景
读多写少:ReentrantReadWriteLock适用于读操作比写操作频繁的场景,因为它允许多个读线程同时访问共享
数据,而写操作是独占的。
缓存:ReentrantReadWriteLock可以用于实现缓存,因为它可以有效地处理大量的读操作,同时保护缓存数据
的一致性