《Java源码分析》:ReentrantLock.unlock 释放锁
来源:互联网 发布:孙笑川 知乎 编辑:程序博客网 时间:2024/06/06 02:20
《Java源码分析》:ReentrantLock.unlock 释放锁
ReentrantLock.unlock()
API给出的介绍为:
试图释放此锁。
如果当前线程是此锁所有者,则将保持计数减 1。如果保持计数现在为 0,则释放该锁。如果当前线程不是此锁的持有者,则抛出 IllegalMonitorStateException。
下面就从源码的角度来分析如何释放锁。
ReentrantLock.lock方法如下,直接调用了AQS类中的release方法。
- 1
- 2
- 3
AQS类中的release方法的代码如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
代码思路:
如果调用tryRelease释放锁成功,返回true。则调用unparkSuccessor函数来将头结点的继任节点唤醒。
下面我们来具体看release(int arg)方法中的tryRelease(int arg)和 unparkSuccessor(Node node).
tryRelease(int arg)
对于独占锁,函数tryRelease的参数arg == 1.即只有一个线程可能拥有锁。其它线程处于阻塞中。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
代码分析
1、先检查当前线程是不是拥有锁的独占线程。如果不是,则抛异常。这是因为线程不能够释放其它线程所拥有的锁。如果是,则进行 2.
2、将AQS状态位减少要释放的次数(对于独占锁次数为1)。如果剩余的状态位为 0(也就是没有线程持有锁).那么当前线程是最后一个持有锁的线程,调用setExclusiveOwnerThread来设置AQS持有锁的独占线程为null.接着进行 3
3、将剩余的状态位写会AQS,如果没有线程持有锁,则返回true,否则返回false
这里c==0决定了是否完全释放了锁。由于ReentrantLock是可重入锁,因此同一个线程可能多重持有锁,那么当且仅当最后一个持有锁的线程释放锁是才能将AQS中持有锁的独占线程清空,这样接下来的操作才需要唤醒下一个需要锁的AQS节点(Node),否则就只是减少锁持有的计数器,并不能改变其他操作。
当tryRelease操作成功后(也就是完全释放了锁),release操作才能检查是否需要唤醒下一个继任节点。这里的前提是AQS队列的头结点需要锁(waitStatus!=0),如果头结点需要锁,就开始检测下一个继任节点是否需要锁操作。
我们在上篇博文中知道acquireQueued操作完成后(拿到了锁),会将当前持有锁的节点设为头结点,所以一旦头结点释放锁,那么就需要寻找头结点的下一个需要锁的继任节点,并唤醒它。
unparkSuccessor(Node node)方法
方法的源码如下,
函数功能:找到当前节点的下一个需要锁的继任节点,并将调用unpark将其唤醒。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
上面代码的思路比较简单。就是找出头结点的下一个需要锁的继任节点然后唤醒。
为什么在unparkSuccessor()函数中是
从队列的后面开始寻找第最后一个waitStatus<=0的节点,然后唤醒,为什么不是从前往后,而是从后往前??
这个目前还没有找到答案
以上就是释放锁的全部过程。
小结
unlock释放锁的大致思想:如果当前线程释放锁成功,则寻找头结点的下一个需要锁的继任节点并唤醒。如果释放锁不成功,则什么也不做。
- 《Java源码分析》:ReentrantLock.unlock 释放锁
- 《Java源码分析》:ReentrantLock.unlock 释放锁
- ReentrantLock源码解析(二):释放锁unlock()
- ReentrantLock源码之二unlock方法解析(锁的释放)
- 第六章 ReentrantLock源码解析2--释放锁unlock()
- 分析ReentrantLock之unlock
- java ReentrantLock源码分析
- 并发编程学习总结(四) :java 显式锁ReentrantLock使用详解之lock()\unlock() 加锁与释放锁
- ReentrantLock(二)Lock.unlock()分析
- 《Java源码分析》:ReentrantLock.lock 锁机制
- 《Java源码分析》:ReentrantLock.lock 锁机制
- Java并发-ReentrantLock源码分析
- java并发-ReentrantLock源码分析
- java并发-ReentrantLock源码分析
- java源码分析:重入锁ReentrantLock
- Java 并发 ---ReentrantLock源码分析
- ReentrantLock解析,lock与unlock方法分析
- 【Java并发编程实战】-----“J.U.C”:ReentrantLock之三unlock方法分析
- workbench使用ssh连接内网数据库
- 欢迎使用CSDN-markdown编辑器
- 面试常客——————Binder学习笔记(一)
- H2Engine服务器引擎介绍
- 【福分系统】项目小结
- 《Java源码分析》:ReentrantLock.unlock 释放锁
- 安装CDH的超详细步骤
- getRawX(),getRawY(),getX(),getY(),getScrollX(),getScrollY()区别
- 268. Missing Number
- Ubuntu+Visual Studio Code
- 一些html5表单知识及EventUtil对象完善
- HTTPS解析
- List与Set的区别,和Collection
- shell 脚本中的if else