并发9:读写锁
Contents
ReadWriteLock
读写锁,并不是 Java 语言特有的,而是一个广为使用的通用技术,所有的读写锁都遵守以 下三条基本原则:
允许多个线程同时读共享变量;
只允许一个线程写共享变量;
如果一个写线程正在执行写操作,此时禁止读线程读共享变量。
读写锁与互斥锁的一个重要区别就是读写锁允许多个线程同时读共享变量,而互斥锁是不允许的,这是读写锁在读多写少场景下性能优于互斥锁的关键。但读写锁的写操作是互斥的, 当一个线程在写共享变量的时候,是不允许其他线程执行写操作和读操作。
快速实现一个缓存
用 ReadWriteLock 快速实现一个通用的缓存工具类。声明了一个 Cache<K, V> 类,其中类型参数 K 代表缓存里 key 的 类型,V 代表缓存里 value 的类型。缓存的数据保存在 Cache 类内部的 HashMap 里面, HashMap 不是线程安全的,这里我们使用读写锁 ReadWriteLock 来保证其线程安全。 ReadWriteLock 是一个接口,它的实现类是 ReentrantReadWriteLock,通过名字你应该 就能判断出来,它是支持可重入的。下面我们通过 rwl 创建了一把读锁和一把写锁。
Cache 这个工具类,我们提供了两个方法,一个是读缓存方法 get(),另一个是写缓存方法 put()。读缓存需要用到读锁,读锁的使用和前面我们介绍的 Lock 的使用是相同的,都是 try{}finally{}这个编程范式。写缓存则需要用到写锁,写锁的使用和读锁是类似的。这样看 来,读写锁的使用还是非常简单的。
1 | class Cache<K,V>{ |
读写锁类似于 ReentrantLock,也支持公平模式和非公平模式。读锁和写锁都实现了 java.util.concurrent.locks.Lock 接口,所以除了支持 lock() 方法外,tryLock()、 lockInterruptibly() 等方法也都是支持的。但是有一点需要注意,那就是只有写锁支持条件 变量,读锁是不支持条件变量的,读锁调用 newCondition() 会抛出 UnsupportedOperationException 异常。
Author: corn1ng
Link: https://corn1ng.github.io/2020/01/12/新版并发/并发9:读写锁/
License: 知识共享署名-非商业性使用 4.0 国际许可协议