代码在后面

读锁 = 共享锁

读锁写锁,公用一个Sync AQS state。

写锁是排他的,看到有人获取锁,他不会去获取,他获取了锁,别人也不会进来获取锁。

写锁的获取跟ReentarntLock一样,每次加1,是一个独占锁,只要有人获取了锁,自己就去排队,排队时候节点是EXCLUSIVE的节点,入队方法acquireQueuedReentarntLock一样,会设置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源码分析的更多相关文章

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

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

  2. ReentrantReadWriteLock 源码分析

    ReentrantReadWriteLock  源码分析: 1:数据结构: 成员变量: private final ReentrantReadWriteLock.ReadLock readerLock ...

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

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

  4. ReentrantReadWriteLock源码分析(一)

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

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

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

  6. ReentrantReadWriteLock源码分析笔记

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

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

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

  8. ReentrantReadWriteLock源码分析及理解

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

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

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

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

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

随机推荐

  1. javascript(五)表达式

    表达式 (expression) JavaScript中的一个短语, JavaScript解释器会将其计算(evaluate) 出一 个结果.程序中的常量是最简单的一类表达式.变量名也是一种简单的表达 ...

  2. 【USACO】香甜的黄油

    这是一道来自USACO的题,一般歪果仁的题都不是很好做,就比如这题 题目描述: 农夫John发现做出全威斯康辛州最甜的黄油的方法:糖.把糖放在一片牧场上,他知道N(1<=N<=500)只奶 ...

  3. Spring Boot 使用 JWT 进行身份和权限验证

    上周写了一个 适合初学者入门 Spring Security With JWT 的 Demo,这篇文章主要是对代码中涉及到的比较重要的知识点的说明. 适合初学者入门 Spring Security W ...

  4. vue项目进入mui.js报错 typeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode .....

    在做项目时,引用mui报错如下 看样子就是不支持严格模式吧. 解决方法是在根目录 下的.babelrc文件里面添加过滤掉.不用严格模式

  5. vue+element下拉框样式的点击按钮

    项目中点击按钮实在太多了,怎么办呢?我们就可以将它们制作成像下拉框那样的类似操作 1.HTML样式部分:关键点在于command 方法和属性 1 <el-dropdown 2 size=&quo ...

  6. 【转载】Gradle学习 第十一章:使用Gradle命令行

    转载地址:http://ask.android-studio.org/?/article/94 This chapter introduces the basics of the Gradle com ...

  7. 交叉编译用于生成aarch64指令的GCC (9.2)

    参考 Building GCC as a cross compiler for Raspberry Pi How to Build a GCC Cross-Compiler 环境 PC: ubuntu ...

  8. 查看 Python 对象的属性

    1 .dir函数可以返回一个对象的所有属性和方法. 示例:查看 int 对象的属性和方法 示例: 查看 dict 对象的属性和方法 标红的这些是不是遇到过? 2.help()调用内置帮助系统 示例 3 ...

  9. 最常见Linux操作

    命令 含义 cd /home/hadoop #把/home/hadoop设置为当前目录 cd .. #返回上一级目录 cd ~ #进入到当前Linux系统登录用户的主目录(或主文件夹).在 Linux ...

  10. 借助模板类自动实现COM连接点接收器(Sink)

    本文的更新:借助模板类自动实现COM连接点接收器(Sink)更新 (2014-06-09 17:09) 最初的代码源自free2000fly的一个标准的 COM 连接点接收器(Sink)的实现, 使用 ...