摘要:我们知道,的作用其实是对类的和的增强,是为了让线程在指定对象上等待,是一种线程之间进行协调的工具。当线程调用对象的方法时,必须拿到和这个对象关联的锁。
本文首发于一世流云的专栏:https://segmentfault.com/blog...一、ReentrantReadWriteLock类简介
ReentrantReadWriteLock类,顾名思义,是一种读写锁,它是ReadWriteLock接口的直接实现,该类在内部实现了具体独占锁特点的写锁,以及具有共享锁特点的读锁,和ReentrantLock一样,ReentrantReadWriteLock类也是通过定义内部类实现AQS框架的API来实现独占/共享的功能。
ReentrantReadWriteLock类具有如下特点:
1.1 支持公平/非公平策略与ReadWriteLock类一样,ReentrantReadWriteLock对象在构造时,可以传入参数指定是公平锁还是非公平锁。
同一读线程在获取了读锁后还可以获取读锁;
同一写线程在获取了写锁之后既可以再次获取写锁又可以获取读锁;
1.3 支持锁降级所谓锁降级,就是:先获取写锁,然后获取读锁,最后释放写锁,这样写锁就降级成了读锁。但是,读锁不能升级到写锁。简言之,就是:
写锁可以降级成读锁,读锁不能升级成写锁。1.4 Condition条件支持
ReentrantReadWriteLock的内部读锁类、写锁类实现了Lock接口,所以可以通过newCondition()方法获取Condition对象。但是这里要注意,读锁是没法获取Condition对象的,读锁调用newCondition() 方法会直接抛出UnsupportedOperationException。
我们知道,condition的作用其实是对Object类的wait()和notify()的增强,是为了让线程在指定对象上等待,是一种线程之间进行协调的工具。1.5 使用示例
当线程调用condition对象的await方法时,必须拿到和这个condition对象关联的锁。由于线程对读锁的访问是不受限制的(在写锁未被占用的情况下),那么即使拿到了和读锁关联的condition对象也是没有意义的,因为读线程之前不需要进行协调。
以下是Oracle官方给出的一个例子:
使用ReentrantReadWriteLock控制对TreeMap的访问(利用读锁控制读操作的访问,利用写锁控制修改操作的访问),将TreeMap包装成一个线程安全的集合,并且利用了读写锁的特性来提高并发访问。
public class RWTreeMap { private final Map二、ReentrantReadWriteLock类/方法声明 2.1 类声明m = new TreeMap (); 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 (String[]) 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(); } } }
内部嵌套类声明:
ReentrantReadWriteLock类有两个内部嵌套类ReadLock和WriteLock,这两个内部类的实例会在ReentrantReadWriteLock类的构造器中创建,并通过ReentrantReadWriteLock类的readLock()和writeLock()方法访问。
ReadLock:
WriteLock:
ReentrantReadWriteLock类的核心方法其实就两个:readLock()和writeLock(),其它都是一些用来监控系统状态的方法,返回的都是某一时刻点的近似值。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/71525.html
摘要:整个包,按照功能可以大致划分如下锁框架原子类框架同步器框架集合框架执行器框架本系列将按上述顺序分析,分析所基于的源码为。后,根据一系列常见的多线程设计模式,设计了并发包,其中包下提供了一系列基础的锁工具,用以对等进行补充增强。 showImg(https://segmentfault.com/img/remote/1460000016012623); 本文首发于一世流云专栏:https...
摘要:关于,最后有两点规律需要注意当的等待队列队首结点是共享结点,说明当前写锁被占用,当写锁释放时,会以传播的方式唤醒头结点之后紧邻的各个共享结点。当的等待队列队首结点是独占结点,说明当前读锁被使用,当读锁释放归零后,会唤醒队首的独占结点。 showImg(https://segmentfault.com/img/remote/1460000016012293); 本文首发于一世流云的专栏:...
摘要:公平策略在多个线程争用锁的情况下,公平策略倾向于将访问权授予等待时间最长的线程。使用方式的典型调用方式如下二类原理的源码非常简单,它通过内部类实现了框架,接口的实现仅仅是对的的简单封装,参见原理多线程进阶七锁框架独占功能剖析 showImg(https://segmentfault.com/img/remote/1460000016012582); 本文首发于一世流云的专栏:https...
摘要:但是,有些操作会依赖于对象的变化过程,此时的解决思路一般就是使用版本号。在变量前面追加上版本号,每次变量更新的时候把版本号加一,那么就会变成。四的引入就是上面所说的加了版本号的。 showImg(https://segmentfault.com/img/remote/1460000016012188); 本文首发于一世流云的专栏:https://segmentfault.com/blo...
摘要:线程可以调用的方法进入阻塞,当计数值降到时,所有之前调用阻塞的线程都会释放。注意的初始计数值一旦降到,无法重置。 showImg(https://segmentfault.com/img/remote/1460000016012041); 本文首发于一世流云的专栏:https://segmentfault.com/blog... 一、CountDownLatch简介 CountDow...
阅读 3707·2021-10-18 13:34
阅读 2396·2021-08-11 11:15
阅读 1201·2019-08-30 15:44
阅读 687·2019-08-26 10:32
阅读 984·2019-08-26 10:13
阅读 2064·2019-08-23 18:36
阅读 1774·2019-08-23 18:35
阅读 523·2019-08-23 17:10