ReentrantReadWriteLock的使用
ReentrantReadWriteLock的规则是:
多线程情况下:读-写互斥、写-读互斥、写-写互斥、读-读共享
验证“读-写互斥、写-读互斥、写-写互斥、读-读共享”
//单个线程 读-读 不互斥
r.lock();
r.lock();
System.out.println("读-读 不互斥");
r.unlock();
r.unlock();
//多个线程 读-读 不互斥
new Thread(() -> {
r.lock();
try {Thread.sleep(2000L);} catch (InterruptedException e) {}
r.unlock();
}).start();
new Thread(() -> {
r.lock();
System.out.println("立刻执行");
r.unlock();
}).start();
//单个线程 读-写 互斥,不存在锁升级
r.lock();
w.lock();
System.out.println("ok");
w.unlock();
r.unlock();
//多个线程 写-读 互斥
new Thread(() -> {
w.lock();
try {Thread.sleep(10000000L);} catch (InterruptedException e) {}
w.unlock();
}).start();
try {Thread.sleep(500L);} catch (InterruptedException e) {}//等第一个线程
new Thread(() -> {
r.lock();
System.out.println("我能获得读锁");
r.unlock();
}).start();
ReentrantReadWriteLock使用场景
对于数据比较敏感的场景,
读锁:在读取数据时是不能出现多次读取不一致的情况的,这点有点像可重复读和幻读,
写锁:写数据时,又不能同时读取数据
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(); }
}
锁降级
单线程情况下有个特殊的点:读-写不互斥、即降级
//单个线程 写-读 不互斥,降级
w.lock();
r.lock();
System.out.println("ok");
r.unlock();
w.unlock();
//降级后,其他线程读不能进来 因为写锁并没有完全释放,如果按照下面这种方式做,那么降级将变的没有任何意义,因为你完全可以用一把写锁就代替了
new Thread(() -> {
w.lock();
r.lock();
System.out.println("我已经降级了");
try {Thread.sleep(2000L);} catch (InterruptedException e) {}
r.unlock();
w.unlock();
}).start();
new Thread(() -> {
r.lock();
System.out.println("我能进去");
r.unlock();
}).start();
//正确的姿势如下,这样就能保证在写锁没释放前转化为读锁,写锁紧接着释放,其他线程的读就可以进去了
new Thread(() -> {
w.lock();
r.lock();
w.unlock();
System.out.println("我已经降级了");
try {Thread.sleep(2000L);} catch (InterruptedException e) {}
r.unlock();
}).start();
new Thread(() -> {
r.lock();
System.out.println("我能进去");
r.unlock();
}).start();
锁降级可以帮助我们拿到当前线程修改后的结果而不被其他线程所破坏
锁降级的典型用法
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private final Lock r = rwl.readLock();
private final Lock w = rwl.writeLock(); w.lock();
//writing
r.lock();
w.unlock();
//reading
r.unlock();
ReentrantReadWriteLock的使用的更多相关文章
- 【Java并发编程实战】-----“J.U.C”:ReentrantReadWriteLock
ReentrantLock实现了标准的互斥操作,也就是说在某一时刻只有有一个线程持有锁.ReentrantLock采用这种独占的保守锁直接,在一定程度上减低了吞吐量.在这种情况下任何的"读/ ...
- 架构师养成记--14.重入锁ReentrantLock 和 读写锁 ReentrantReadWriteLock
ReentrantLock 有嗅探锁定和多路分支等功能,其实就是synchronized,wait,notify的升级. this锁定当前对象不方便,于是就有了用new Object()来作为锁的解决 ...
- 【JUC】JDK1.8源码分析之ReentrantReadWriteLock(七)
一.前言 在分析了锁框架的其他类之后,下面进入锁框架中最后一个类ReentrantReadWriteLock的分析,它表示可重入读写锁,ReentrantReadWriteLock中包含了两种锁,读锁 ...
- Lock、ReentrantLock、synchronized、ReentrantReadWriteLock使用
先来看一段代码,实现如下打印效果: 1 2 A 3 4 B 5 6 C 7 8 D 9 10 E 11 12 F 13 14 G 15 16 H 17 18 I 19 20 J 21 22 K 23 ...
- Java多线程系列--“JUC锁”08之 共享锁和ReentrantReadWriteLock
概要 Java的JUC(java.util.concurrent)包中的锁包括"独占锁"和"共享锁".在“Java多线程系列--“JUC锁”02之 互斥锁Ree ...
- ReentrantReadWriteLock读写锁详解
一.读写锁简介 现实中有这样一种场景:对共享资源有读和写的操作,且写操作没有读操作那么频繁.在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取共享资源:但是如果一个线 ...
- ReentrantReadWriteLock类和ReentrantLock类的区别
Java.util.concurrent.locks包定义了两个锁类,ReentrantLock和ReentrantReadWriteLock类. 当有很多线程都从某个数据结构中读取数据而很少有线程对 ...
- 多线程之ReentrantReadWriteLock
java5以后在java.util.concurrent包下,有很多的并发类,可以让我们摆脱java5时,笨重的写法来满足多线程,而且提供了更加丰富的使用场景能力 其中,在locks包下,提供了 Re ...
- Java中的显示锁 ReentrantLock 和 ReentrantReadWriteLock
在Java1.5中引入了两种显示锁,分别是可重入锁ReentrantLock和可重入读写锁ReentrantReadWriteLock.它们分别实现接口Lock和ReadWriteLock.(注意:s ...
- java ReentrantReadWriteLock
// read and write lock is mutual exclusion lock //Listing 7-3. Using ReadWriteLock to Satisfy a Dict ...
随机推荐
- 洛谷P1342 请柬
P1342 请柬 题目描述 在电视时代,没有多少人观看戏剧表演.Malidinesia古董喜剧演员意识到这一事实,他们想宣传剧院,尤其是古色古香的喜剧片.他们已经打印请帖和所有必要的信息和计划.许多学 ...
- bzoj4435: [Cerc2015]Juice Junctions(最小割树+hash)
传送门 首先最大流等于最小割,那么可以转化为最小割树来做(不知道什么是最小割树的可以看看这题->这里) 具体的做法似乎是$hash[i][j]$表示最小割为$i$时点$j$是否与$S$连通 然后 ...
- bzoj2502: 清理雪道(有源汇有上下界最小流)
传送门 别说话,自己看,我不会->这里 我这里用的建图方法是先跑一次最大流,连上$(t,s,inf)$之后再跑一遍,然后答案就是之前连的那条边的反向边的流量 据说还有种方法是连上$(t,s,in ...
- Cef3 学习资料
fanfeilong/cefutil CEF General Usage(CEF3预览) CEF General Usage(CEF3预览) 介绍 CEF全称Chromium Embedded Fra ...
- [转][iOS Crash文件分析]-如何使用symbolicatecrash工具
上传一软件,被拒了,自己测试了n遍都未出现这个情况,今天用symbolicatecrash工具分析了一下苹果提供的Crash文件,最终查到是 - (void)mapView:(MKMapView *) ...
- es6的箭头函数转换为普通函数,以及将await/async函数转为普通函数
箭头函数转为普通函数: 1. 安装babel-preset-es2015 npm install babel-preset-es2015 --save-dev 2.在.babelrc文件夹中: & ...
- 关于STL库中的max min swap
嗯... 不得不说c++中的STL库是一个神奇的东西 可以使你的代码显得更加简洁.... 今天就只讲STL中的三个鬼畜: max min swap 具体操作 ...
- centos7.3下配置本地yum仓库
部署openstack时,网络yum源安装慢,而且经常中的提示找不到mirrors,所以配置一个本地的安装源很有必要,来解决这个揪心的问题. 安装:yum install yum-utils crea ...
- Unity 行为树-共享变量
一.引言 有以下小场景: 节点A:发现了 敌人. 节点B:追逐敌人. 对于同一个敌人物体,节点AB之间是如何传递数据 的呢? 行为树节点AB之间,需要一个中间变量Temp来传递数据. A发现了敌人,将 ...
- 关于js框架 dwz 与 yii的的分页 以及筛选的结合
此为jicheng1014 原创....地址为http://jicheng1014.cnblogs.com dwz是一个不错的前端框架 但是 注意 所有的后端 都是要自己写的 常见的应用是 ...