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的使用的更多相关文章

  1. 【Java并发编程实战】-----“J.U.C”:ReentrantReadWriteLock

    ReentrantLock实现了标准的互斥操作,也就是说在某一时刻只有有一个线程持有锁.ReentrantLock采用这种独占的保守锁直接,在一定程度上减低了吞吐量.在这种情况下任何的"读/ ...

  2. 架构师养成记--14.重入锁ReentrantLock 和 读写锁 ReentrantReadWriteLock

    ReentrantLock 有嗅探锁定和多路分支等功能,其实就是synchronized,wait,notify的升级. this锁定当前对象不方便,于是就有了用new Object()来作为锁的解决 ...

  3. 【JUC】JDK1.8源码分析之ReentrantReadWriteLock(七)

    一.前言 在分析了锁框架的其他类之后,下面进入锁框架中最后一个类ReentrantReadWriteLock的分析,它表示可重入读写锁,ReentrantReadWriteLock中包含了两种锁,读锁 ...

  4. 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 ...

  5. Java多线程系列--“JUC锁”08之 共享锁和ReentrantReadWriteLock

    概要 Java的JUC(java.util.concurrent)包中的锁包括"独占锁"和"共享锁".在“Java多线程系列--“JUC锁”02之 互斥锁Ree ...

  6. ReentrantReadWriteLock读写锁详解

    一.读写锁简介 现实中有这样一种场景:对共享资源有读和写的操作,且写操作没有读操作那么频繁.在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取共享资源:但是如果一个线 ...

  7. ReentrantReadWriteLock类和ReentrantLock类的区别

    Java.util.concurrent.locks包定义了两个锁类,ReentrantLock和ReentrantReadWriteLock类. 当有很多线程都从某个数据结构中读取数据而很少有线程对 ...

  8. 多线程之ReentrantReadWriteLock

    java5以后在java.util.concurrent包下,有很多的并发类,可以让我们摆脱java5时,笨重的写法来满足多线程,而且提供了更加丰富的使用场景能力 其中,在locks包下,提供了 Re ...

  9. Java中的显示锁 ReentrantLock 和 ReentrantReadWriteLock

    在Java1.5中引入了两种显示锁,分别是可重入锁ReentrantLock和可重入读写锁ReentrantReadWriteLock.它们分别实现接口Lock和ReadWriteLock.(注意:s ...

  10. java ReentrantReadWriteLock

    // read and write lock is mutual exclusion lock //Listing 7-3. Using ReadWriteLock to Satisfy a Dict ...

随机推荐

  1. 洛谷P1282 多米诺骨牌

    P1282 多米诺骨牌 题目描述 多米诺骨牌有上下2个方块组成,每个方块中有1~6个点.现有排成行的 上方块中点数之和记为S1,下方块中点数之和记为S2,它们的差为|S1-S2|.例如在图8-1中,S ...

  2. 2017-10-12 NOIP模拟赛

      斐波那契 /* 相同颜色的节点与父亲节点的差相等,且是一个小于它的最大斐波那契数 所以降两个点同时减去小与它的最大斐波那契数,直到两点相等 */ #include<cstdio> ; ...

  3. Nacos深入浅出(九)

    然而Nacos的发布操作并不是上面我们想的那样通过代理去实现,通过下面的代码我们分析下: public class NacosConfigurationPropertiesBindingPostPro ...

  4. Git练习1

  5. GTY's gay friends 线段树判断区间是否有相同数字

    http://acm.hdu.edu.cn/showproblem.php?pid=5172 判断一个区间是否为全排列是: 1.区间总和 = (1 + R - L + 1) * (R - L + 1) ...

  6. Seven-segment Display 贪心选择,快速判断能否有解

    https://csacademy.com/contest/round-39/task/seven-segment-display/ 可以知道,只有1是无解 而且肯定是选出来的位数约小越好. 位数 = ...

  7. Python metaclasses

    metaclasses元类:就像对象是类的实例一样,类是它的元类的实例.调用元类可以创建类. metaclass使用type来创建类,type可以被继承生成新的元类. 这个和C#的反射很相似. 下面是 ...

  8. Hive 基本语法操练(五):Hive 的 JOIN 用法

    Hive 的 JOIN 用法 hive只支持等连接,外连接,左半连接.hive不支持非相等的join条件(通过其他方式实现,如left outer join),因为它很难在map/reduce中实现这 ...

  9. ArrayList相关方法介绍及源码分析

    目录 ArrayList简介: ArrayList 相关方法介绍 代码表示 相关方法源码分析 ArrayList简介: java.util.ArrayList 是我们最常用的一个类,ArrayList ...

  10. 敏捷开发(Agile development)

    敏捷开发(Agile development) 敏捷开发是一种以人为核心.迭代.循序渐进的开发方法.在敏捷开发中,软件项目的构建被切分成多个子项目,各个子项目的成果都经过测试,具备集成和可运行的特征. ...