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 ...
随机推荐
- 2017-10-7 清北刷题冲刺班a.m
测试 A 消失的数字 文件名 输入文件 输出文件 时间限制 空间限制del.cpp/c/pas del.in del.out 1s 512MB题目描述现在,我的手上有 n 个数字,分别是 a 1 ,a ...
- Mysql-2-数据库基础
(1)mysql是一个小型关系型数据库管理系统. (2)mysql是一个快速.多线程.多用户.健壮的SQL数据库服务器.与其他数据库管理系统比,mysql有以下的优势: mysql是一个关系数据库管理 ...
- 在 CentOS7 安装 ELK【转】
ELK是一个成熟的日志系统,主要功能有收集.分析.检索,详细见 elastic官网. 本文主要介绍如何在CentOS7下安装最新版本的ELK,当然现在docker已经有完全配置成功的elk容器,安装配 ...
- django进阶之缓存
Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行 ...
- 老男孩Day1作业(二):三级菜单
作业需求: 1. 运行程序输出第一级菜单 2. 选择一级菜单某项,输出二级菜单,同理输出三级菜单 3. 菜单数据保存在文件中 4. 让用户选择是否要退出 5. 有返回上一级菜单的功能 1)编写思路 编 ...
- java中静态代码块的用法 static用法详解和static静态导入
(一)java 静态代码块 静态方法区别一般情况下,如果有些代码必须在项目启动的时候就执行的时候,需要使用静态代码块,这种代码是主动执行的;需要在项目启动的时候就初始化,在不创建对象的情况下,其他程序 ...
- 前端实现Tab切换栏
tab切换,所需的 UI 只有两组元素 - Header 和 Tab,下面介绍几种不同的实现方法和他们的优缺点 本文主要说一些 CSS 的实现方法.最好的方法是 第四种 => label + i ...
- 得到RequestVO
import java.io.IOException; import java.nio.charset.Charset; import javax.servlet.ServletInputStream ...
- scrapy可视化管理工具spiderkeeper使用笔记
http://www.scrapyd.cn/doc/156.html 入门中文教程 spiderkeeper是一款开源的spider管理工具,可以方便的进行爬虫的启动,暂停,定时,同时可以查看分布式 ...
- Chapter10
package scala import java.io.{PrintStream, PrintWriter}import java.util.Date import scala.util.loggi ...