juc:ReentrantReadWriteLock
收藏:
【死磕Java并发】—–J.U.C之读写锁:ReentrantReadWriteLock
参考:
搞定ReentrantReadWriteLock 几道小小数学题就够了
简介:
重入锁ReentrantLock是排他锁,排他锁在同一时刻仅有一个线程可以进行访问,
但是在大多数场景下,大部分时间都是提供读服务,而写服务占有的时间较少。
然而读服务不存在数据竞争问题,如果一个线程在读时禁止其他线程读势必会导致性能降低。
所以就提供了读写锁。 读写锁维护着一对锁,一个读锁和一个写锁。通过分离读锁和写锁,使得并发性比一般的排他锁有了较大的提升:
在同一时间可以允许多个读线程同时访问,但是在写线程访问时,所有读线程和写线程都会被阻塞。
读写锁的主要特性:
公平性:支持公平性和非公平性。
重入性:支持重入。读写锁最多支持65535个递归写入锁和65535个递归读取锁。
锁降级:遵循获取写锁、获取读锁在释放写锁的次序,写锁能够降级成为读锁
读写锁ReentrantReadWriteLock实现接口ReadWriteLock,该接口维护了一对相关的锁,一个用于只读操作,另一个用于写入操作。
只要没有 writer,读取锁可以由多个 reader 线程同时保持。写入锁是独占的。
JCU包中读写锁接口(ReadWriteLock)的重要实现类ReentrantReadWriteLock。主要实现读共享,写互斥功能,对比单纯的互斥锁在共享资源使用场景为频繁读取及少量修改的情况下可以较好的提高性能。
ReadWriteLock接口简单说明
ReadWriteLock接口只定义了两个方法:
public interface ReadWriteLock { /** * Returns the lock used for reading. * * @return the lock used for reading */ Lock readLock(); /** * Returns the lock used for writing. * * @return the lock used for writing */ Lock writeLock(); }
通过调用相应方法获取读锁或写锁,获取的读锁及写锁都是Lock接口的实现,可以如同使用Lock接口一样使用(其实也有一些特性是不支持的)。
ReentrantReadWriteLock使用示例
读写锁的使用并不复杂,可以参考以下使用示例:
class RWDictionary { private final Map<String, Data> m = new TreeMap<String, Data>(); private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); private final Lock r = rwl.readLock(); private final Lock w = rwl.writeLock(); public Data get(String key) { r.lock(); try { return m.get(key); } finally { r.unlock(); } } public String[] allKeys() { r.lock(); try { return m.keySet().toArray(); } finally { r.unlock(); } } public Data put(String key, Data value) { w.lock(); try { return m.put(key, value); } finally { w.unlock(); } } public void clear() { w.lock(); try { m.clear(); } finally { w.unlock(); } } }
与普通重入锁使用的主要区别在于需要使用不同的锁对象引用读写锁,并且在读写时分别调用对应的锁。

浙公网安备 33010602011771号