ReentrantLock源码阅读
默认构造方法初始化同步器为非公平同步器
/**
* Creates an instance of {@code ReentrantLock}.
* This is equivalent to using {@code ReentrantLock(false)}.
*/
public ReentrantLock() {
sync = new NonfairSync();
}
lock()方法调用的是sync的lock()方法
public void lock() {
sync.lock();
} final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
如果将state从0改为1成功,那么将属性exclusiveOwnerThread改为当前线程,代表获得锁成功
protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
} protected final void setExclusiveOwnerThread(Thread thread) {
exclusiveOwnerThread = thread;
}
修改失败走acquire,参数arg为1
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
三步走
1.tryAcquire调用的是nonfairTryAcquire
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
//aquire为1
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//这个逻辑什么时候会走?其他线程第一次抢锁失败,然后恰好获得锁的线程释放了锁?
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//获得锁的线程重入会走这个逻辑
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
2.又一次抢锁失败,且不是当前线程重入,tryAcquire返回false,走下一步逻辑acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
2.1 addWaiter(Node.EXCLUSIVE) (将新节点插入尾节点之后,如果尾节点为空,初始化一个新节点,没有线程,既是头也是尾,返回新节点有thread没有addwaiter)
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
//如果有尾节点,将当前节点插入尾节点之后(可能其他线程也在做此事,失败了没关系下一步会处理)
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
} Node(Thread thread, Node mode) { // Used by addWaiter
this.nextWaiter = mode;
this.thread = thread;
} private Node enq(final Node node) {
for (;;) {
Node t = tail;
//尾节点为空,初始化一个新节点,头和尾都指向他
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
//将node节点放入尾节点之后,一次次直到成功
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
} Node() { // Used to establish initial head or SHARED marker
}
2.2 acquireQueued
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
//如果前一个结点是头节点,尝试获得锁,获得锁后,将自己设为头节点,前头节点置空
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
//将当前节点的前一个结点的waitStatus改为-1(循环直到成功),挂起当前节点lockSupport.park
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
ReentrantLock源码阅读的更多相关文章
- Java多线程——ReentrantLock源码阅读
上一章<AQS源码阅读>讲了AQS框架,这次讲讲它的应用类(注意不是子类实现,待会细讲). ReentrantLock,顾名思义重入锁,但什么是重入,这个锁到底是怎样的,我们来看看类的注解 ...
- Java多线程——ReentrantReadWriteLock源码阅读
之前讲了<AQS源码阅读>和<ReentrantLock源码阅读>,本次将延续阅读下ReentrantReadWriteLock,建议没看过之前两篇文章的,先大概了解下,有些内 ...
- 《java.util.concurrent 包源码阅读》13 线程池系列之ThreadPoolExecutor 第三部分
这一部分来说说线程池如何进行状态控制,即线程池的开启和关闭. 先来说说线程池的开启,这部分来看ThreadPoolExecutor构造方法: public ThreadPoolExecutor(int ...
- Java并发系列[5]----ReentrantLock源码分析
在Java5.0之前,协调对共享对象的访问可以使用的机制只有synchronized和volatile.我们知道synchronized关键字实现了内置锁,而volatile关键字保证了多线程的内存可 ...
- Rpc框架dubbo-client(v2.6.3) 源码阅读(二)
接上一篇 dubbo-server 之后,再来看一下 dubbo-client 是如何工作的. dubbo提供者服务示例, 其结构是这样的!dubbo://192.168.11.6:20880/com ...
- ThreadPoolExecutor 源码阅读
目录 ThreadPoolExecutor 源码阅读 Executor 框架 Executor ExecutorService AbstractExecutorService 构造器 状态 Worke ...
- 【详解】ThreadPoolExecutor源码阅读(二)
系列目录 [详解]ThreadPoolExecutor源码阅读(一) [详解]ThreadPoolExecutor源码阅读(二) [详解]ThreadPoolExecutor源码阅读(三) AQS在W ...
- 【详解】ThreadPoolExecutor源码阅读(一)
系列目录 [详解]ThreadPoolExecutor源码阅读(一) [详解]ThreadPoolExecutor源码阅读(二) [详解]ThreadPoolExecutor源码阅读(三) 工作原理简 ...
- 死磕 java同步系列之ReentrantLock源码解析(二)——条件锁
问题 (1)条件锁是什么? (2)条件锁适用于什么场景? (3)条件锁的await()是在其它线程signal()的时候唤醒的吗? 简介 条件锁,是指在获取锁之后发现当前业务场景自己无法处理,而需要等 ...
- CyclicBarrier源码阅读
一种允许多个线程全部等待彼此都到达某个屏障的同步机制 使用 多个线程并发执行同一个CyclicBarrier实例的await方法时,每个线程执行这个方法后,都会被暂停,只有当最后一个线程执行完awai ...
随机推荐
- 逆向学习物联网-网关ESP8266-02模块AT指令的测试
1.硬件测试环境搭建 https://item.taobao.com/item.htm?spm=a1z09.2.0.0.58582e8dOkitcE&id=623715787845&_ ...
- signalR client属性中的大致方法
T All { get; } 相当于持久连接中的 Broadcast. T AllExcept(params string[] excludeConnectionIds); 给排除本人所有人发送消息. ...
- pyqt5 弹窗大全--修复版
1 from PyQt5.QtWidgets import * 2 from PyQt5.QtCore import Qt, pyqtSignal, QTimer 3 4 5 class MyWind ...
- Linux日常指令
Linux: https://man.linuxde.net/ Linux命令大全 基础指令 终端输入: #shutdown -h now : 立即关机 #ls: 显示路径下所有的文件: ...
- zabbix监控mysql数据库——qps和tps
首先可以继续顺着zabbix监控mysql继续往下做 1.首先在42的继续编写qps和tps 1.1qps 在41服务端查询: 1.2 tps 2.在web进行查看
- 在Unity3D中开发的Sketch Shader
Pencil Sketch Shader 特点 此素描渲染风格的Shader是顶点片元Shader,由本人手动编写完成. 此素描渲染风格的Shader已经在移动设备真机上进行过测试,可以直接应用到您的 ...
- python批量导出、安装依赖库文件
导出: 在原环境中 pip freeze > fname.txt 安装: 在新环境中 pip install -r fname.txt 其中fname.txt 可以随意命名,其存储安装库文件列 ...
- Git系列 -> git commit 报错 “Invalid syntax in configuration ini file.”
git commit 报错 提示信息为 "Invalid syntax in configuration ini file." 解决办法: 方法一:使用-n or --no-ver ...
- vue-cli项目以script标签方式引入js的方法
在public/index.html中强行添加script标签(可引入本地js和远程js,本地js需放在public内,不能放assets内) 在要使用这个js的地方,将相关对象添加到eslint的全 ...
- springboot[2.3.4.RELEASE]application.properties常用配置
常用配置 spring.profiles.active=@spring.profiles.active@ pom文件中定义的配置文件 server.port=8080 web默认访问端口 server ...