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 ...
随机推荐
- 洛谷P2580(trie)
第一行一个整数 n,表示班上人数.接下来 n 行,每行一个字符串表示其名字(互不相同,且只含小写字母,长度不超过 50).第 n+2 行一个整数 m,表示教练报的名字.接下来 m 行,每行一个字符串表 ...
- redhat Enterprise Linux 6 VNC安装
redhat Enterprise Linux 6.2 beta VNC安装经验 VNC(Virtual Network Computing)是可操控远程的计算机的软件,任何人都可免费取得该软件,其 ...
- WampServer的安装
首先安装好Microsoft Visual C++ 然后再安装WampServer 安装过程很简单 错误解决 运行后为黄色图标(成功运行应该为绿色图标) 解决办法: 1.80端口是否被占用 你的80端 ...
- BootStrap系统
BootStrsp的引入: <!-- 新 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="// ...
- Pipenv: Python包管理神器
Pipenv旨在将最好的包管理机制(bundler, composer, npm, cargo, yarn等等)带到Python中去. 它会为你的项目自动创建和管理virtualenv,也会在安装和移 ...
- 洛谷P2746 校园网Network of Schools
题目描述 一些学校连入一个电脑网络.那些学校已订立了协议:每个学校都会给其它的一些学校分发软件(称作"接受学校").注意即使 \(B\) 在 \(A\) 学校的分发列表中, \(A ...
- Webpack热加载和React(其中有关于include和exclude的路径问题)
看了几个React配合webpack的教程,大部分都因为版本问题过时了.终于找到了一个不错的教程.记录下其中的知识点. 首先万分感谢这个教程的制作者.少走了许多弯路,正在学习webpack的小伙伴可以 ...
- 自增长 auto_increment
auto_increment :自动编号,一般与主键组合使用.一个表里面只有一个自增默认情况下,起始值为1,每次的增量为1. 例子:create table tb5( id int primar ...
- 017 Letter Combinations of a Phone Number 电话号码的字母组合
给定一个数字字符串,返回数字所有可能表示的字母组合. 输入:数字字符串 "23"输出:["ad", "ae", "af" ...
- Java面向对象_常用类库api
StringBuffer 例: public class StringBufferDemo { /** * @param args */ public static void main(String[ ...