ReentrantReadWriteLock源码分析
代码在后面
读锁 = 共享锁
读锁写锁,公用一个Sync AQS state。
写锁是排他的,看到有人获取锁,他不会去获取,他获取了锁,别人也不会进来获取锁。
写锁的获取跟ReentarntLock一样,每次加1,是一个独占锁,只要有人获取了锁,自己就去排队,排队时候节点是EXCLUSIVE的节点,入队方法acquireQueued和ReentarntLock一样,会设置OwnerThread。
读锁先获取锁,后面有读锁进来,多个读线程共存时候,第一个读线程设置firstReader,其余读线程设置threadLocals属性,然后获取锁,读锁每次增加65536,
写锁再进来,就去排队。
读锁再又进来,读锁还是去排队,
读锁不会设置OwnerThread,只是会state增加65536,写锁会忽略大于65536的部分。
state!=0,state去掉前16位=0,说明有读锁进去,写锁不进去。
State高位存储读锁获取次数,低位存储写锁获取次数。
设置threadLocals属性的读线程unlock时候清除threadLocalMap的标记,设置firstReader的读线程unlock时候设置firstReader=null,并且state减65536,
//读锁进来,首先判断state后16位,有写锁就去排队,没有写锁就设置firstReader或者firstReaderHoldCount++或者当前线程的threadLocals并且state增加65536
//写锁进来时候,首先判断state,有读锁写锁就去排队,
1.读锁进来,不看owenerThread,看的是state,去掉前面16位=0,说明没有写线程获取锁,就设置firstReader或者threadLocalMap,state增加65536。state去掉前面16位!=0说明有写线程获得了锁,就去排队。如果队列第一个是写线程,就去排队。 如果后面还有读线程进来,照样。
2.写锁进来,state!=0,state去掉前面16位=0,说明state已经加了几个65536了,说明有线程在读,写锁要去排队。state=0说明没有写线程获取锁,没有读线程在读,就去获取锁。state!=0,state去掉前面16位!=0,说明state有写线程获取锁,就去排队。
读锁每次加65536,不设置owenerThread。写锁每次加1,设置owenerThread。
读:去掉前面16!=0就去排队,队列空设置firstReader或者threadLocalMap,第一个节点是写线程排队,第一个节点是读线程设置firstReader或者threadLocalMap。
写:state!=0,去掉前面16位=0去排队,state=0获取锁。


if (exclusiveCount(c) != 0 /*去掉前面16位,*/ && getExclusiveOwnerThread() != current)
获取读锁时候,去掉前面16位!=0,OwnerThread() = current,说明里面有写锁了,并且是自己。说明一个线程先获取写锁在获取读锁,那么这个线程占据了owenerThread和firstReader或者threadLocalMap。
public class ReadWriteLockTest<E> {
private final Map<String, String> map = new TreeMap<>();
private final ReentrantReadWriteLock1 lock = new ReentrantReadWriteLock1();
//写的时候,不能读不能写。 读的时候,不能写可以读。
//读线程获取锁,其他读线程可以获取锁,写线程不能获取锁
//写线程获取锁,读线程写线程不能获取锁
private final ReentrantReadWriteLock1.ReadLock readLock = lock.readLock();
private final ReentrantReadWriteLock1.WriteLock writeLock = lock.writeLock();
public ReadWriteLockTest() {
}
public String write(String key, String value) throws InterruptedException {
writeLock.lock();//写锁是排他的,看到有人获取锁,他不会去获取,他获取了锁别人也不会进来获取锁。
readLock.lock();
// writeLock.lockInterruptibly();
// writeLock.tryLock();
try {
return map.put(key, value);
} finally {
writeLock.unlock();//写锁释放,就唤醒AQS
}
}
public String read(String key) throws InterruptedException {
readLock.lock();//获取的是共享锁
// writeLock.lock();
// readLock.lockInterruptibly();
// readLock.tryLock();
try {
return map.get(key);
} finally {
readLock.unlock();//读锁全部释放完了,才会去唤醒AQS
}
}
private static ReadWriteLockTest<Integer> tt = new ReadWriteLockTest<Integer>();
public static void main(String[] args) {
new Thread(() -> {
int i = ;
while (true) {
Write w = new Write("写--" + (i++));
w.start();
}
}).start();
new Thread(() -> {
int j = ;
while (true) {
Read s1 = new Read("读--" + (j++));
s1.start();
// Read s2 = new Read("读--" + (j++));
// s2.start();
// Read s3 = new Read("读--" + (j++));
// s3.start();
// s1.interrupt();
// s2.interrupt();
// s3.interrupt();
}
}).start();
}
static int i =;static int j = ;
static class Write extends Thread {
Write(String name) {
super(name);
}
@Override
public void run() {
try {
tt.write((i++)+"",(j++)+"");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class Read extends Thread {
Read(String name) {
super(name);
}
@Override
public void run() {
try {
tt.read((i--)+"");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
ReentrantReadWriteLock源码分析的更多相关文章
- 【Java并发编程】16、ReentrantReadWriteLock源码分析
一.前言 在分析了锁框架的其他类之后,下面进入锁框架中最后一个类ReentrantReadWriteLock的分析,它表示可重入读写锁,ReentrantReadWriteLock中包含了两种锁,读锁 ...
- ReentrantReadWriteLock 源码分析
ReentrantReadWriteLock 源码分析: 1:数据结构: 成员变量: private final ReentrantReadWriteLock.ReadLock readerLock ...
- Java并发指南10:Java 读写锁 ReentrantReadWriteLock 源码分析
Java 读写锁 ReentrantReadWriteLock 源码分析 转自:https://www.javadoop.com/post/reentrant-read-write-lock#toc5 ...
- ReentrantReadWriteLock源码分析(一)
此处源码分析,主要是基于读锁,非公平机制,JDK1.8. 问题: 1.ReentrantReadWriteLock是如何创建读锁与写锁? 2.读锁与写锁的区别是什么? 3.锁的重入次数与获取锁的线程数 ...
- Java显式锁学习总结之五:ReentrantReadWriteLock源码分析
概述 我们在介绍AbstractQueuedSynchronizer的时候介绍过,AQS支持独占式同步状态获取/释放.共享式同步状态获取/释放两种模式,对应的典型应用分别是ReentrantLock和 ...
- ReentrantReadWriteLock源码分析笔记
ReentrantReadWriteLock包含两把锁,一是读锁ReadLock, 此乃共享锁, 一是写锁WriteLock, 此乃排它锁. 这两把锁都是基于AQS来实现的. 下面通过源码来看看Ree ...
- ReentrantReadWriteLock 源码分析以及 AQS 共享锁 (二)
前言 上一篇讲解了 AQS 的独占锁部分(参看:ReentrantLock 源码分析以及 AQS (一)),这一篇将介绍 AQS 的共享锁,以及基于共享锁实现读写锁分离的 ReentrantReadW ...
- ReentrantReadWriteLock源码分析及理解
本文结构 读写锁简介:介绍读写锁.读写锁的特性以及类定义信息 公平策略及Sync同步器:介绍读写锁提供的公平策略以及同步器源码分析 读锁:介绍读锁的一些常用操作和读锁的加锁.解锁的源码分析 写锁:介绍 ...
- 多线程之美7一ReentrantReadWriteLock源码分析
目录 前言 在多线程环境下,为了保证线程安全, 我们通常会对共享资源加锁操作,我们常用Synchronized关键字或者ReentrantLock 来实现,这两者加锁方式都是排他锁,即同一时刻最多允许 ...
- Java并发编程笔记之读写锁 ReentrantReadWriteLock 源码分析
我们知道在解决线程安全问题上使用 ReentrantLock 就可以,但是 ReentrantLock 是独占锁,同时只有一个线程可以获取该锁,而实际情况下会有写少读多的场景,显然 Reentrant ...
随机推荐
- springboot的pom.xml配置
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven ...
- iOS批量添加SDK自动打包GUI工具
背景 1.之前在给游戏开发商做SDK接入技术支持的时候,很多cp对iOS开发技术并不是很了解,对接SDK和打包都很迷糊,虽然我们根据他们的开发环境输出了不同的插件解决方案,这一步已经把接入SDK的复杂 ...
- 浓缩版java8新特性
目录 一.Lambda 1.定义/设计原因 2.结构 3.规则 4.使用 二.函数式接口 1.定义 2.设计原因 3.使用 三.方法引用 1.定义/设计原因 2.使用 四.接口的默认方法 1.定义 2 ...
- 面试官:优化代码中大量的if/else,你有什么方案?
一个快速迭代的项目,时间久了之后,代码中可能会充斥着大量的if/else,嵌套6.7层,一个函数几百行,简!直!看!死!人! 这个无限循环嵌套,只是总循环的一部分...我已经绕晕在黄桷湾立交 仔细数了 ...
- 10年前错过比特币,如今有斯坦福区块链项目pi币,对标btc,手机免费挖矿详细教程。
这一个斯坦福几个博士创业者做一个项目,目前还处于早期阶段,除了每天点一下挖矿之外,貌似不需要其他的操作,不需要耗费流量资源和手机大量的运算能力,就是一个安静的App而已....国内目前知道的人还不太多 ...
- Nginx 高级配置-实现多域名HTTPS
Nginx 高级配置-实现多域名HTTPS 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Nginx支持基于单个IP实现多域名的功能 Nginx支持基于单个IP实现多域名的功能 ...
- 逆向破解之160个CrackMe —— 022
CrackMe —— 022 160 CrackMe 是比较适合新手学习逆向破解的CrackMe的一个集合一共160个待逆向破解的程序 CrackMe:它们都是一些公开给别人尝试破解的小程序,制作 c ...
- 测试基础【第六篇】bug要素及其生命周期
bug的要素 为了让开发人员更准确.更快的看懂Bug,测试需要按照一定的规范提交bug. 缺陷id:一般由缺陷管理系统自动生成: 缺陷标题:概要描述缺陷: 发现人:一般是缺陷管理系统自动获取当前用户: ...
- VMware下安装Ubuntu虚拟机
ubuntu系统是以桌面应用为主的.当下最火的linux操作系统,具有实用的界面,并且完全免费. 在Ubuntu的 Linux 世界里,已经不再只是简陋的界面+命令行,而是一款华丽时尚且无比实用的操作 ...
- USACO Superprime Rib
洛谷 P1218 [USACO1.5]特殊的质数肋骨 Superprime Rib 洛谷传送门 JDOJ 1673: Superprime Rib JDOJ传送门 题目描述 农民约翰的母牛总是产生最好 ...