ReentrantReadWriteLock  源码分析:

1:数据结构:

成员变量:

private final ReentrantReadWriteLock.ReadLock readerLock; //读取锁

private final ReentrantReadWriteLock.WriteLock writerLock; //写入锁

final Sync sync;    //Sync 对象,继承AQS对象

2:构造函数:

public ReentrantReadWriteLock() {

this(false);

}

public ReentrantReadWriteLock(boolean fair) {   //默认 fair= false

sync = fair ? new FairSync() : new NonfairSync();  //默认创建一个 NonfairSync

readerLock = new ReadLock(this);     //创建读取锁

writerLock = new WriteLock(this);     //创建写入锁

}

3:接下来分析ReadLock 读取锁;

1):成员变量:

private final Sync sync;   // ReadLock 内部维护的Sync对象,和ReentrantReadWriteLock中维护的Sync对象一致;

2):构造方法:

protected ReadLock(ReentrantReadWriteLock lock) {

sync = lock.sync;   //将ReentrantReadWriteLock 构造函数中创建的Sync对象赋给ReadLock 中的Sync属性

}

4:下面分析ReadLock中的lock方法;

public void lock() {

sync.acquireShared(1);

}

acquireShared方法如下:

public final void acquireShared(int arg) {  // arg=1

if (tryAcquireShared(arg) < 0)

doAcquireShared(arg);

}

下面依次分析 tryAcquireShared  doAcquireShared这两个方法:

1): tryAcquireShared    方法:

protected final int tryAcquireShared(int unused) {  // unused=1

Thread current = Thread.currentThread();  //当前线程

int c = getState();          //锁被持有的次数

if (exclusiveCount(c) != 0 &&

getExclusiveOwnerThread() != current)  //若为互斥锁 且持有锁的线程不是当前线程则返回-1;

return -1;

int r = sharedCount(c);  /获取锁的共享次数

if (!readerShouldBlock() &&

r < MAX_COUNT && //锁不需要阻塞等待,共享次数小于最大值,共享次数+1

compareAndSetState(c, c + SHARED_UNIT)) {

if (r == 0) {  //第一次获取读取锁 则返回1 获取成功

firstReader = current;

firstReaderHoldCount = 1;

} else if (firstReader == current) {  //同一线程第二次后获取锁

firstReaderHoldCount++;    //持有锁的次数++

} else {   //当其他线程获取锁时会进入这个逻辑

HoldCounter rh = cachedHoldCounter;

if (rh == null || rh.tid != getThreadId(current))

cachedHoldCounter = rh = readHolds.get();

else if (rh.count == 0)

readHolds.set(rh);

rh.count++;

}

return 1;

}

return fullTryAcquireShared(current);  //当队列中首个节点是独占锁时会进入这个逻辑  这里就不分析了

}

ReentrantReadWriteLock 源码分析的更多相关文章

  1. 【Java并发编程】16、ReentrantReadWriteLock源码分析

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

  2. Java并发指南10:Java 读写锁 ReentrantReadWriteLock 源码分析

    Java 读写锁 ReentrantReadWriteLock 源码分析 转自:https://www.javadoop.com/post/reentrant-read-write-lock#toc5 ...

  3. ReentrantReadWriteLock源码分析(一)

    此处源码分析,主要是基于读锁,非公平机制,JDK1.8. 问题: 1.ReentrantReadWriteLock是如何创建读锁与写锁? 2.读锁与写锁的区别是什么? 3.锁的重入次数与获取锁的线程数 ...

  4. Java显式锁学习总结之五:ReentrantReadWriteLock源码分析

    概述 我们在介绍AbstractQueuedSynchronizer的时候介绍过,AQS支持独占式同步状态获取/释放.共享式同步状态获取/释放两种模式,对应的典型应用分别是ReentrantLock和 ...

  5. ReentrantReadWriteLock源码分析笔记

    ReentrantReadWriteLock包含两把锁,一是读锁ReadLock, 此乃共享锁, 一是写锁WriteLock, 此乃排它锁. 这两把锁都是基于AQS来实现的. 下面通过源码来看看Ree ...

  6. ReentrantReadWriteLock 源码分析以及 AQS 共享锁 (二)

    前言 上一篇讲解了 AQS 的独占锁部分(参看:ReentrantLock 源码分析以及 AQS (一)),这一篇将介绍 AQS 的共享锁,以及基于共享锁实现读写锁分离的 ReentrantReadW ...

  7. ReentrantReadWriteLock源码分析及理解

    本文结构 读写锁简介:介绍读写锁.读写锁的特性以及类定义信息 公平策略及Sync同步器:介绍读写锁提供的公平策略以及同步器源码分析 读锁:介绍读锁的一些常用操作和读锁的加锁.解锁的源码分析 写锁:介绍 ...

  8. 多线程之美7一ReentrantReadWriteLock源码分析

    目录 前言 在多线程环境下,为了保证线程安全, 我们通常会对共享资源加锁操作,我们常用Synchronized关键字或者ReentrantLock 来实现,这两者加锁方式都是排他锁,即同一时刻最多允许 ...

  9. Java并发编程笔记之读写锁 ReentrantReadWriteLock 源码分析

    我们知道在解决线程安全问题上使用 ReentrantLock 就可以,但是 ReentrantLock 是独占锁,同时只有一个线程可以获取该锁,而实际情况下会有写少读多的场景,显然 Reentrant ...

随机推荐

  1. Python requests库的使用(一)

    requests库官方使用手册地址:http://www.python-requests.org/en/master/:中文使用手册地址:http://cn.python-requests.org/z ...

  2. reduce求和真方便

    1.reduce的用法. reduce是JavaScript中的一个方法,常用于数组求和,接收两个参数,第一个参数为累加函数,第二个参数为初始值,这个初始值是前面那个累加函数的参数.如果不指定初始值, ...

  3. mysql数据库被攻击

    好久没有登录我自己的服务器了,今日登录发现mysql数据库沦陷了.我的数据库名字叫linkorganizer,是一个链接管理数据库.旧表已经丢失了,整个数据库只剩下一个warning表,它是黑客留下的 ...

  4. webpack篇,结合理论与实际,加以透彻分析!

    Webpack篇 开始着手项目打包的一些东西,还不是特别懂,一边学习,一边做笔记好啦. 1.webpack的概念.Webpack 是当下最热门的前端资源模块化管理和打包工具.任何形式的资源都可以视作模 ...

  5. 关于创建node服务

    1.环境条件准备: A.确定node已经创建 B.npm或cnpm已经下载,npm和cnpm其实是一个道理 C.mysql或者使用其他数据库已经安装(本例使用mysql) 2.开始创建,首先新建一个文 ...

  6. affine_trans_pixel 和 affine_trans_point_2d的区别

    affine_trans_pixel 和 affine_trans_point_2d的不同在于所使用的坐标系原点不同,affine_trans_pixel 使用的是像素坐标系, 即原点位于图像的左上角 ...

  7. CTF挑战赛丨网络内生安全试验场第一季答题赛火热开启

    前期回顾:挑战世界级“人机大战”,更有万元奖金等你来拿 网络内生安全试验场自上线以来,受到了业内的极大重视与关注. 自9月2日报名通道开启后,报名量更是持续高升,上百名精英白帽踊跃报名. 至此,网络内 ...

  8. [20190507]sga_target=0注意修改_kghdsidx_count设置.txt

    [20190507]sga_target=0注意修改_kghdsidx_count设置.txt --//昨天遇到一例视图定义太复杂导致长时间分析sql语句出现library cache lock等待事 ...

  9. 001-Zabbix 服务安装

    Zabbix 服务安装 [官方地址]点我快速打开文章 1.安装 Zabbix 1.1 下载 Zabbix 清华源 rpm -ivh https://mirrors.tuna.tsinghua.edu. ...

  10. Linux学习之常用命令(三)

    常用命令之工作目录 显示当前目录 pwd[选项] 切换目录 cd [文件路径] cd /root 注意:可以使用Tab键进行路径补齐 cd .. >>返回上次的目录 显示目录以及文件信息 ...