ReentrantReadWriteLock 锁Java 的并发包提供了读写锁 ReentrantReadWriteLock ,其拥有两个锁:读锁-共享锁;写锁-排他锁。
ReentrantReadWriteLock 源码分析 1. 所以我们对数据进行并发访问是不会有问题的,于是诞生了 读锁 和 写锁的概念,在 Java 中提供的 ReentrantReadWriteLock 就是一个具体实现。 对于 ReentrantReadWriteLock,当写操作时,其它线程无法读取或写入数据,而当读操作时,其它线程无法写数据,但却可以读取数据。 介绍一下线程进入读写锁的条件。 // 维护两个锁,这两个锁里面的实现就是 sync private final ReentrantReadWriteLock.ReadLock readerLock; private final ReentrantReadWriteLock.WriteLock
概述 ReentrantReadWriteLock是Lock的另一种实现方式,我们已经知道了ReentrantLock是一个排他锁,同一时间只允许一个线程访问,而ReentrantReadWriteLock 在实际应用中,大部分情况下对共享数据(如缓存)的访问都是读操作远多于写操作,这时ReentrantReadWriteLock能够提供比排他锁更好的并发性和吞吐量。 ReentrantReadWriteLock支持以下功能: 支持公平与非公平的获取锁方式。 import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock 代码如下: import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock
针对这种场景,JAVA 的并发包提供了读写锁 ReentrantReadWriteLock,它表示两个锁,一个是读操作相关的锁,称为共享锁;一个是写相关的锁,称为排他锁。 volatile Map<String,Object> map=new HashMap<>(); //创建读写锁对象 private ReadWriteLock readWriteLock=new ReentrantReadWriteLock 演示读写锁降级 public class Demo1 { public static void main(String[] args) { //可重入读写锁对象 ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock ();//读锁 ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();//写锁 //锁降级
ReentrantReadWriteLock 结构 final Sync sync; // 构造函数 public ReentrantReadWriteLock(boolean fair) { ReadLock implements Lock, java.io.Serializable { private final Sync sync; protected ReadLock(ReentrantReadWriteLock WriteLock implements Lock, java.io.Serializable { private final Sync sync; protected WriteLock(ReentrantReadWriteLock
构造方法分析 //无参构造方法调用有参构造方法,并且传入一个参数为false public ReentrantReadWriteLock() { this(false);//-----> protected ReadLock(ReentrantReadWriteLock lock) { //此时把ReentrantReadWriteLock里的属性sync引用赋值给 里的属性sync)、(reentrantReadWriteLock.readLock的属性sync)和(reentrantReadWriteLock.writeLock的属性sync)是同一个sync( 源码及实现原理分析_fxkcsdn的博客-CSDN博客_reentrantreadwritelock原理 读锁上锁过程 在没有读锁和写锁的情况申请读锁 ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(); //在没有读锁和写锁的情况下申请读锁 reentrantReadWriteLock.readLock()
因此引入ReentrantReadWriteLock。 一个ReentrantReadWriteLock同时只能存在一个写锁但是可以存在多个读锁,但不能同时存在写锁和读锁。 一体两面,读写互斥,读读共享 ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); public void write readWriteLock = new ReentrantReadWriteLock(); ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock 在ReentrantReadWriteLock中,当读锁被使用时,如果有线程尝试获取写锁,该写线程会被阻塞。 ,读写锁比传统的synchronized速度要快很多, 原因就是在于 ReentrantReadWriteLock支持读并发 StampedLock横空出世 ReentrantReadWriteLock
上回说到ReentrantLock,今天来谈谈读写锁(ReentrantLock)和其具体实现ReentrantReadWriteLock。 看这篇文章前,强烈建议你回到先读懂ReentrantLock,因为ReentrantReadWriteLock其实是在ReentrantLock的基础上实现的,可以参考我之前的博客ReentrantLock 看到这里,你应该已经理解了什么叫做“读写锁”,接下来我们直接看下jdk中ReentrantReadWriteLock的实现,再次建议先阅读ReentrantLock的具体实现。 ? public ReentrantReadWriteLock(boolean fair) { sync = fair ? ReentrantReadWriteLock的出现大幅提升了多读少写场景下的性能问题,但它依旧有自己的缺点,就是它可能会导致写饥饿。
那么ReentrantReadWriteLock(读写锁)是如何实现的呐,按照之前的说法,ReentrantReadWriteLock应该也是借助AQS来做吧,毕竟人家提供了那么多方法,不用白不用么。 通过查看ReentrantReadWriteLock类的体系结构,我们看到主要有Syn、NofairSyn、FairSyn、readlock和writeLock。 ReentrantReadWriteLock的类结构如 ? 其中方法基本都是操作Syn来进行的。因此解析Syn成为我们必须要面对的问题。 ?
java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock GoodsInfo goodsInfo; /** * 创建读写锁,默认使用非公平锁 */ private final ReadWriteLock lock = new ReentrantReadWriteLock
ReentrantReadWriteLock 源码分析 1. 所以我们对数据进行并发访问是不会有问题的,于是诞生了 读锁 和 写锁的概念,在 Java 中提供的 ReentrantReadWriteLock 就是一个具体实现。 对于 ReentrantReadWriteLock,当写操作时,其它线程无法读取或写入数据,而当读操作时,其它线程无法写数据,但却可以读取数据。 介绍一下线程进入读写锁的条件。 // 维护两个锁,这两个锁里面的实现就是 sync private final ReentrantReadWriteLock.ReadLock readerLock; private final ReentrantReadWriteLock.WriteLock
ReentrantReadWriteLock 结构 final Sync sync; // 构造函数 public ReentrantReadWriteLock(boolean fair) { ReadLock implements Lock, java.io.Serializable { private final Sync sync; protected ReadLock(ReentrantReadWriteLock WriteLock implements Lock, java.io.Serializable { private final Sync sync; protected WriteLock(ReentrantReadWriteLock
针对这种场景,JAVA的并发包提供了读写锁ReentrantReadWriteLock,它表示两个锁,一个是读操作相关的锁,称为共享锁;一个是写相关的锁,称为排他锁,描述如下: 线程进入读锁的前提条件: 源码解读 我们先来看下 ReentrantReadWriteLock 类的整体结构: public class ReentrantReadWriteLock implements ReadWriteLock , java.io.Serializable { /** 读锁 */ private final ReentrantReadWriteLock.ReadLock readerLock; /** 使用默认(非公平)的排序属性创建一个新的 ReentrantReadWriteLock */ public ReentrantReadWriteLock() { this(false); } /** 使用给定的公平策略创建一个新的 ReentrantReadWriteLock */ public ReentrantReadWriteLock
概述 ReentrantReadWriteLock是Lock的另一种实现方式,我们已经知道了ReentrantLock是一个排他锁,同一时间只允许一个线程访问,而ReentrantReadWriteLock 在实际应用中,大部分情况下对共享数据(如缓存)的访问都是读操作远多于写操作,这时ReentrantReadWriteLock能够提供比排他锁更好的并发性和吞吐量。 ReentrantReadWriteLock支持以下功能: 1)支持公平和非公平的获取锁的方式; 2)支持可重入。 rwl = new ReentrantReadWriteLock(); 5 6 void processCachedData() { 7 rwl.readLock(). 域 ReentrantReadWriteLock含有两把锁readerLock和writerLock,其中ReadLock和WriteLock都是内部类。
ReentrantReadWriteLock与ReentrantLock的区别: ReentrantLock:同一时间只能有一个线程执行ReentrantLock.lock()后面的代码,这样虽然可以保证线程安全 ReentrantReadWriteLock:有两种锁也就是分别有读和写两种锁,在不需要操作实例变量时,可用读锁,在操作实例变量时,用写锁,这样就可以提升程序的运行效率。
lock = new ReentrantReadWriteLock(false); static final Lock r = lock.readLock(); static () { this(false); } /** * Creates a new {@code ReentrantReadWriteLock} with writeLock() { return writerLock; } public ReentrantReadWriteLock.ReadLock readLock() { return readerLock; } 可以看出来在通过ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); 默认使用的是不公平锁这里补充一下、 公平锁和不公平锁的区别 writeLock() { return writerLock; } public ReentrantReadWriteLock.ReadLock readLock() { return readerLock
针对公平锁而言,readerShouldBlock会判断前面是不是有等待的节点(不管是不是互斥锁),而针对非公平锁而言则是判断同步队列第一个节点是不是互斥锁(写锁)。
ReentrantReadWriteLock类 ReentrantReadWriteLock():使用非公平策略创建一个ReentrantReadWriteLock对象; ReentrantReadWriteLock ReadLock类 ReentrantReadWriteLock.ReadLock(ReentrantReadWriteLock lock):使用ReentrantReadWriteLock创建ReadLock WriteLock类 ReentrantReadWriteLock.WriteLock(ReentrantReadWriteLock lock):使用ReentrantReadWriteLock创建WriteLock //ReadLock是ReentrantReadWriteLock中的静态内部类,它是读取锁的实现 private final ReentrantReadWriteLock.ReadLock 对象构建 protected WriteLock(ReentrantReadWriteLock lock) { //在ReentrantReadWriteLock
读写锁案例 JavaDoc文档写的非常详细,给我们举了一个ReentrantReadWriteLock的使用例子,我们直接来看看: class CachedData { Object data; volatile boolean cacheValid; // 创建读写锁实例 final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock ReentrantReadWriteLock架构总览 ReentrantReadWriteLock是ReadWriteLock的实现,其实看到这个名儿:可重入的读写锁,我们就大概可以猜测一下它的意思了。 () { this(false); } /** 初始化读锁和写锁实例 */ public ReentrantReadWriteLock(boolean fair) ReentrantReadWriteLock的三个特性: 公平性:支持公平和非公平两种模式。 重入性:支持重入,读写锁都支持最多65535个。
而很多时候会出现“读多写少”的情况,若用 ReentrantLock 会降低并发量,此时就比较适合 ReentrantReadWriteLock 出场了。 ReentrantReadWriteLock 是读写锁,它维护了一对锁:一个读锁,一个写锁。读锁之间是共享的,写锁是互斥的。 ReentrantReadWriteLock 对象 // true 为公平,false 为非公平 public ReentrantReadWriteLock(boolean fair) { sync ReentrantReadWriteLock 的主要代码就分析到这里,下面简单分析其用法和使用场景。 「读多写少」的场景下,ReentrantReadWriteLock 比 ReentrantLock 有更高的并发性。 3.