详解tryAcquire()、addWaiter()、acquireQueued()
作者:胖虎。。 时间:2022-07-30 10:24:05
本文实例为大家分享了tryAcquire()、addWaiter()、acquireQueued()的用法 ,供大家参考,具体内容如下
tryAcquire()
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;
}
先判断state是否为0,如果为0就执行上面提到的lock方法的前半部分,通过CAS操作将state的值从0变为1,否则判断当前线程是否为exclusiveOwnerThread,然后把state++,也就是重入锁的体现,我们注意前半部分是通过CAS来保证同步,后半部分并没有同步的体现,原因是:后半部分是线程重入,再次获得锁时才触发的操作,此时当前线程拥有锁,所以对ReentrantLock的属性操作是无需加锁的。如果tryAcquire()获取失败,则要执行addWaiter()向等待队列中添加一个独占模式的节点。
addWaiter()
/**
* Creates and enqueues node for current thread and given mode.
*
* @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
* @return the new node
*/
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为当前线程,Node.EXCLUSIVE 是独占锁, Node.SHARED 是共享锁。
先找到等待队列的tail节点pred,如果pred!=null,就把当前线程添加到pred后面进入等待队列,如果不存在tail节点执行enq()
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
这里进行了循环,如果此时存在了tail就执行同上一步骤的添加队尾操作,如果依然不存在,就把当前线程作为head结点。
插入节点后,调用acquireQueued()进行阻塞
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;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
先获取当前节点的前一节点p,如果p是head的话就再进行一次tryAcquire(arg)操作,如果成功就返回,否则就执行shouldParkAfterFailedAcquire、parkAndCheckInterrupt来达到阻塞效果;
以上所述是小编给大家介绍的tryAcquire()、addWaiter()、acquireQueued()的用法详解整合网站的支持!
来源:https://blog.csdn.net/weixin_38003389/article/details/85935982
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
Java实现简单的扫雷小程序
![](https://img.aspxhome.com/file/2023/6/63806_0s.jpg)
spring boot2结合mybatis增删改查的实现
![](https://img.aspxhome.com/file/2023/4/61644_0s.png)
java学生管理系统界面简单实现(全)
java 使用idea将工程打成jar并创建成exe文件类型执行的方法详解
![](https://img.aspxhome.com/file/2023/2/60702_0s.png)
Java使用iTextPDF生成PDF文件的实现方法
![](https://img.aspxhome.com/file/2023/7/58687_0s.png)
Java中 ? extends T 和 ? super T的理解
解决nacos升级spring cloud 2020.0无法使用bootstrap.yml的问题
![](https://img.aspxhome.com/file/2023/3/61773_0s.png)
Spring MVC深入学习之启动初始化过程
![](https://img.aspxhome.com/file/2023/3/57423_0s.jpg)
ThreadLocal使用案例_动力节点Java学院整理
SpringMVC @RequestBody自动转json Http415错误的解决
![](https://img.aspxhome.com/file/2023/0/63070_0s.jpg)
Android 实现可任意拖动的悬浮窗功能(类似悬浮球)
java8 实现提取集合对象的每个属性
C语言 OutputDebugString与格式化输出函数OutputDebugPrintf案例详解
![](https://img.aspxhome.com/file/2023/3/105163_0s.jpg)
Spring使用@Autowired为抽象父类注入依赖代码实例
Flutter Widgets粘合剂CustomScrollView NestedScrollView滚动控件
![](https://img.aspxhome.com/file/2023/9/120089_0s.webp)
java中ArrayList和LinkedList的区别详解
Java日常练习题,每天进步一点点(7)
![](https://img.aspxhome.com/file/2023/8/59978_0s.png)
java 使用foreach遍历集合元素的实例
java 多态性详解及常见面试题
简单谈谈Java中的栈和堆
![](https://img.aspxhome.com/file/2023/3/61163_0s.png)