当前位置:网站首页>ReentrantLock学习之---基础方法
ReentrantLock学习之---基础方法
2022-07-26 18:05:00 【virtuousOne】
Reentrant通过lock()方法进行加锁。
public void lock() {
sync.acquire(1);
}

继续往下看,发现acquire里面也是调用其他方法
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
针对tryAcquire,接下来看下里面的逻辑。本次主要是进入的公平锁的该方法的实现。
这里就需要用到上篇博客中的state, 获取当前线程的状态进而处理;
当 c == 0 时表示: 当前处于无锁状态
在该逻辑,检查队列中是否在当前线程之前等待
hasQueuedPredecessors(): 返回 true 表示线程前面有等待者;
compareAndSetState(0, acquires): 返回true 表示抢占锁成功
另一个逻辑.即为重入锁逻辑, 进行更新state的值,每次+1.
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1);
}
/** * Fair version of tryAcquire. Don't grant access unless * recursive call or no waiters or is first. * 抢占锁: 抢占成功 true; * 抢占失败 false; */
protected final boolean tryAcquire(int acquires) {
// 当前线程
final Thread current = Thread.currentThread();
// AQS state值
int c = getState();
// 成立 表示AQS 处于无锁状态
if (c == 0) {
// 检查队列中是否在当前线程之前又等待者....
// hasQueuedPredecessors() 返回true,表示当前线程前面有等待者; false 表示当前无等待者,直接尝试获取锁
// 条件二 :compareAndSetState(0, acquires) 成功说明当前线程抢占锁成功 ,失败说明存在竞争, 且当前线程竞争失败
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
// 设置当前线程为独占者线程
setExclusiveOwnerThread(current);
return true;
}
}
// 说明当前线程就是独占锁线程
else if (current == getExclusiveOwnerThread()) {
// 锁重入的逻辑
// nextc : 下次更新的值
int nextc = c + acquires;
// 越界判断,当重入深度很深时,会导致 nextc < 0, int达到最大后,+1 变负数。
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
// 更新操作
setState(nextc);
return true;
}
// 1. CAS失败
// 2. c > 0 且 ownerThread != currentThread
return false;
}
}
接下来看下addWaiter()方法
该方法主要是将线程放入到队列中,再队列中是进行双向绑定,也及为双向链表的结构队列。
使用双向链表:新加入队列和删除锁的时候双向链表再时间和空间上更节约。
private Node addWaiter(Node mode) {
// 构建 Node ,把当前线程封装到对象node中
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
// 快速入队
// 获取队尾结点 保存到 pred变量中
Node pred = tail;
// 条件成立: 队列中已经有 node
if (pred != null) {
// 当前节点的prev 指向pred
node.prev = pred;
// CAS成功, 说明node入队成功
if (compareAndSetTail(pred, node)) {
// 前置节点指向为当前node,完成双向绑定
pred.next = node;
return node;
}
}
// 完整入队
enq(node);
return node;
}
很明显,加入队列的具体逻辑在enq()方法中。
用了自旋入队的方式,只有当前封装的node成功了才会跳出循环。
整个线程第一个入队的有一个逻辑.
private Node enq(final Node node) {
// 自旋入队,当前node入队成功后,才会跳出循环
for (;;) {
Node t = tail;
// 1.当前队列时空队列 tail = null
// 说明当前锁被占用,且当前线程 有可能是第一个获取锁失败的线程
if (t == null) {
// Must initialize
// 作为当前系统的第一个线程,需要做什么?
// 1.当前锁的线程,它获取锁时,直接tryAcquire成功了,没有注释队列中添加任何node
// 2.为自己追加node
// CAS成功,说明当前线程成为 head.next节点
// 线程需要为当前持锁的线程 创建head
if (compareAndSetHead(new Node()))
tail = head;
// 没有return, 继续循环
} else {
// 普通入队方式,只不过在for中,会保证一定入队成功
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
边栏推荐
- 微软默默给 curl 捐赠一万美元,半年后才通知
- SSM integration - exception handler and project exception handling scheme
- 2022 chemical automation control instrument test question simulation test platform operation
- Write a starter
- 我酷故我在
- MySQL - 多表查询与案例详解
- 2022t elevator repair examination questions and online simulation examination
- MySQL exercises elementary 45 questions (Unified table)
- LeetCode简单题之第一个出现两次的字母
- rancher部署kubernetes集群
猜你喜欢

一些时序建模策略(一)

The class jointly built by famous oarsmen is new, and Professor qiuxipeng of Fudan University broadcast it live on Tuesday!

2022g1 industrial boiler stoker certificate question bank and simulation examination

JS uses readLine to realize terminal input data

2022上海市安全员C证操作证考试题库模拟考试平台操作

详细介绍@GetMapping和@PostMapping的区别

(ICLR-2022)TADA!用于视频理解的时间自适应卷积

Brand new! Uncover the promotion route of Ali P5 Engineer ~p8 architect

Tensor RT's int8 quantization principle

Basic module and example pytorch learning
随机推荐
likeshop外卖点餐系统开源啦100%开源无加密
MongoDB stats统计集合占用空间大小
【Swoole系列3.1】进程、线程、协程,面试你被问了吗?
CoVOS:无需解码!利用压缩视频比特流的运动矢量和残差进行半监督的VOS加速(CVPR 2022)...
详细介绍@GetMapping和@PostMapping的区别
【考研词汇训练营】Day 13 —— reliance,expert,subject,unconscious,photograph,exaggeration,counteract
2022上海市安全员C证操作证考试题库模拟考试平台操作
模板进阶(跑路人笔记)
基础模块及算例#pytorch学习
MySQL日志介绍
Utility website recommendations
MySQL - 多表查询与案例详解
Gongfu developer community is settled! On July 30!
Write a thesis and read this one
Interview summary of some large factories
The diagram of user login verification process is well written!
Verification palindrome string II of leetcode simple question
MySQL学习笔记-2.如何提高sql语句的查询性能
Briefly describe the 11 core functional modules of MES system
rancher部署kubernetes集群