ReentrantLock源码之二unlock方法解析(锁的释放)
来源:互联网 发布:mac os x 10.11.6 dmg 编辑:程序博客网 时间:2024/05/21 19:40
在前面一节中,我们分析了ReentrantLock.lock()方法,接下来我们接着分析ReentrantLock.unlock()方法。
1.ReentrantLock.unlock()分析
(1)首先尝试释放锁,如果要求释放数等于锁状态数,那么将锁状态位清0,清除锁所有者,返回true;否则返回false;
(2)如果(1)返回的是true,说明锁完全释放。接下来将检查等待队列,并选择下一个节点恢复(该节点必须是waitStatus),
如果该节点不存在或者被取消,则选择从尾节点开始,选取最靠近头节点的等待节点,同时清理队列中线程被取消的节点;
大家回忆下lock()实现机制,新节点是从尾部插入的。这就说明AQS里面的 CLH其实是一个FIFO队列(用双链表实现的FIFO队列).
(3)如果(1)返回false,说明锁只是部分释放,当前线程仍旧持有该锁;
1java.util.concurrent.locks.ReentrantLock
2 public void unlock() {
3 sync.release(1);
4 }
5
6java.util.concurrent.locks.AbstractQueuedSynchronizer
7public final boolean release(int arg) {
8 if (tryRelease(arg)) {
9 Node h = head;
10 if (h != null && h.waitStatus != 0)
11 unparkSuccessor(h);
12 return true;
13 }
14 return false;
15 }
16
17
18 protected final boolean tryRelease(int releases) {
19 int c = getState() - releases; //重入锁加锁的次数-释放数量
20 if (Thread.currentThread() != getExclusiveOwnerThread()) //判断独占锁是否为当前线程所有
21 throw new IllegalMonitorStateException();
22 boolean free = false;
23 if (c == 0) { //加锁次数=释放数量
24 free = true;
25 setExclusiveOwnerThread(null); //清除锁拥有者标识
26 }
27 setState(c); //设置加锁状态
28 return free;
29 }
30
31
32 /**
33 * Wakes up node's successor, if one exists.
34 *
35 * @param node the node
36 */
37 private void unparkSuccessor(Node node) {
38 /*
39 * Try to clear status in anticipation of signalling. It is
40 * OK if this fails or if status is changed by waiting thread.
41 */
42 compareAndSetWaitStatus(node, Node.SIGNAL, 0); //清除头节点signal状态
43
44 /*
45 * Thread to unpark is held in successor, which is normally
46 * just the next node. But if cancelled or apparently null,
47 * traverse backwards from tail to find the actual
48 * non-cancelled successor.
49 */
50 Node s = node.next;
51 if (s == null || s.waitStatus > 0) { //等待队列唤醒的竞争满足FIFO,本段代码主要是寻找最靠近头节点的,且waitStatus为signal、condition的链表节点
52 s = null;
53 for (Node t = tail; t != null && t != node; t = t.prev)
54 if (t.waitStatus <= 0)
55 s = t;
56 }
57 if (s != null)
58 LockSupport.unpark(s.thread);
59 }
2 public void unlock() {
3 sync.release(1);
4 }
5
6java.util.concurrent.locks.AbstractQueuedSynchronizer
7public final boolean release(int arg) {
8 if (tryRelease(arg)) {
9 Node h = head;
10 if (h != null && h.waitStatus != 0)
11 unparkSuccessor(h);
12 return true;
13 }
14 return false;
15 }
16
17
18 protected final boolean tryRelease(int releases) {
19 int c = getState() - releases; //重入锁加锁的次数-释放数量
20 if (Thread.currentThread() != getExclusiveOwnerThread()) //判断独占锁是否为当前线程所有
21 throw new IllegalMonitorStateException();
22 boolean free = false;
23 if (c == 0) { //加锁次数=释放数量
24 free = true;
25 setExclusiveOwnerThread(null); //清除锁拥有者标识
26 }
27 setState(c); //设置加锁状态
28 return free;
29 }
30
31
32 /**
33 * Wakes up node's successor, if one exists.
34 *
35 * @param node the node
36 */
37 private void unparkSuccessor(Node node) {
38 /*
39 * Try to clear status in anticipation of signalling. It is
40 * OK if this fails or if status is changed by waiting thread.
41 */
42 compareAndSetWaitStatus(node, Node.SIGNAL, 0); //清除头节点signal状态
43
44 /*
45 * Thread to unpark is held in successor, which is normally
46 * just the next node. But if cancelled or apparently null,
47 * traverse backwards from tail to find the actual
48 * non-cancelled successor.
49 */
50 Node s = node.next;
51 if (s == null || s.waitStatus > 0) { //等待队列唤醒的竞争满足FIFO,本段代码主要是寻找最靠近头节点的,且waitStatus为signal、condition的链表节点
52 s = null;
53 for (Node t = tail; t != null && t != node; t = t.prev)
54 if (t.waitStatus <= 0)
55 s = t;
56 }
57 if (s != null)
58 LockSupport.unpark(s.thread);
59 }
阅读全文
0 0
- ReentrantLock源码之二unlock方法解析(锁的释放)
- ReentrantLock源码解析(二):释放锁unlock()
- 第六章 ReentrantLock源码解析2--释放锁unlock()
- 《Java源码分析》:ReentrantLock.unlock 释放锁
- 《Java源码分析》:ReentrantLock.unlock 释放锁
- ReentrantLock解析,lock与unlock方法分析
- AbstractQueuedSynchronizer源码解析之ReentrantLock(二)
- 分析ReentrantLock之unlock
- 推荐: ReentrantLock源码之一lock方法解析(锁的获取)
- 并发编程学习总结(四) :java 显式锁ReentrantLock使用详解之lock()\unlock() 加锁与释放锁
- ReentrantLock(二)Lock.unlock()分析
- “J.U.C”:ReentrantLock之三unlock方法分析(r)
- “J.U.C”:ReentrantLock之三unlock方法分析
- jdk源码解读-并发包-Lock-ReentrantLock(1)--lock()与unlock()方法走读
- ReentrantLock使用详解(1)之lock/unlock
- AbstractQueuedSynchronizer源码解析之ReentrantLock(一)
- Java并发编程之ReentrantLock源码解析
- 【Java并发编程实战】-----“J.U.C”:ReentrantLock之三unlock方法分析
- String类型的replaceAll函数
- 不同服务器之间的文件拷贝
- 自定义按钮的标题宽度、高度
- 判断参数数据类型
- C#高级篇 7
- ReentrantLock源码之二unlock方法解析(锁的释放)
- 代理模式
- [Leetcode] 253. Meeting Rooms II 解题报告
- React Native 用法介绍
- 线程与内核绑定
- 游戏编程入门(10):播放数字声音效果
- android验证通用类
- mysql实现分组排序
- TensorFlow学习---实现mnist手写数字识别