一、定义

release(int) 是 AQS(AbstractQueuedSynchronizer)中的一个核心方法,用于在独占模式下释放同步状态。如果释放成功,则会唤醒等待队列中的后继节点,使其有机会获取同步状态

1、release(int) 方法的作用

  • 功能:释放同步状态(独占模式),并唤醒等待队列中的后继节点

  • 返回值:如果成功释放同步状态,则返回 true;否则返回 false

二、release(int) 方法的源码

以下是 release(int) 方法的源码及其详细解析:

public final boolean release(int arg) {
if (tryRelease(arg)) { // 尝试释放同步状态
// 队列头节点
Node h = head;
// 头节点什么时候是空?没有发生锁竞争,没有竞争线程创建哨兵节点
// 条件成立说明阻塞队列有等待线程,需要唤醒 head 节点后面的线程
if (h != null && h.waitStatus != 0) {
unparkSuccessor(h); // 唤醒后继节点
}
return true;
}
return false;
}

1、tryRelease(int arg) 方法

  • 作用:尝试释放同步状态,由子类实现。

  • 返回值:如果成功释放同步状态,则返回 true;否则返回 false。

  • 示例:

  • 子类需要重写此方法以实现具体的同步逻辑

2、unparkSuccessor(Node node) 方法

  • 作用:唤醒当前节点的后继节点。

  • 参数:

    • node:当前节点(通常是头节点)

         // 找到队列中距离 head 最近的一个没取消的 Node,unpark唤醒线程恢复其运行
      private void unparkSuccessor(Node node) {
      // 当前节点的状态
      int ws = node.waitStatus;
      if (ws < 0) {
      // 【尝试重置状态为 0】,因为当前节点要完成对后续节点的唤醒任务了,不需要 -1 了
      compareAndSetWaitStatus(node, ws, 0);
      }
      // 找到需要 unpark 的节点,当前节点的下一个
      Node s = node.next;
      if (s == null || s.waitStatus > 0) { // 如果后继节点为空或已取消不能唤醒,则从队尾开始查找,需要找到距离头节点最近的非取消的节点
      s = null;
      for (Node t = tail; t != null && t != node; t = t.prev) {
      // 说明当前线程状态需要被唤醒
      if (t.waitStatus <= 0) {
      // 置换引用
      s = t;
      }
      }
      }
      // 【找到合适的可以被唤醒的 node,则唤醒线程】
      if (s != null) {
      LockSupport.unpark(s.thread);
      }
      }

3、compareAndSetWaitStatus(Node node, int expect, int update) 方法

  • 作用:通过 CAS 操作更新节点的 waitStatus。

  • 源码:

4、LockSupport.unpark(Thread thread) 方法

  • 作用:唤醒指定的线程。

  • 源码:

5、release(int) 方法的执行流程

1、调用 tryRelease(int) 尝试释放同步状态。

2、如果成功,则检查头节点是否存在且 waitStatus 不为 0。

3、如果满足条件,则调用 unparkSuccessor(Node) 唤醒后继节点。

4、返回 true 表示释放成功;否则返回 false。

三、总结

AQS的release(int)方法底层源码的更多相关文章

  1. Java并发包源码学习之AQS框架(四)AbstractQueuedSynchronizer源码分析

    经过前面几篇文章的铺垫,今天我们终于要看看AQS的庐山真面目了,建议第一次看AbstractQueuedSynchronizer 类源码的朋友可以先看下我前面几篇文章: <Java并发包源码学习 ...

  2. Android开发之漫漫长途 Ⅵ——图解Android事件分发机制(深入底层源码)

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  3. 为什么很多类甚者底层源码要implements Serializable ?

    为什么很多类甚者底层源码要implements Serializable ? 在碰到异常类RuntimeException时,发现Throwable实现了 Serializable,还有我们平进的ja ...

  4. List-LinkedList、set集合基础增强底层源码分析

    List-LinkedList 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 继上一章继续讲解,上章内容: List-ArreyLlist集合基础增强底层源码分析:https:// ...

  5. 从底层源码浅析Mybatis的SqlSessionFactory初始化过程

    目录 搭建源码环境 POM依赖 测试SQL Mybatis全局配置文件 UserMapper接口 UserMapper配置 User实体 Main方法 快速进入Debug跟踪 源码分析准备 源码分析 ...

  6. Java泛型底层源码解析-ArrayList,LinkedList,HashSet和HashMap

    声明:以下源代码使用的都是基于JDK1.8_112版本 1. ArrayList源码解析 <1. 集合中存放的依然是对象的引用而不是对象本身,且无法放置原生数据类型,我们需要使用原生数据类型的包 ...

  7. HashMap和ConcurrentHashMap的区别,HashMap的底层源码

    HashMap本质是数组加链表,根据key取得hash值,然后计算出数组下标,如果多个key对应到同一个下标,就用链表串起来,新插入的在前面. ConcurrentHashMap在HashMap的基础 ...

  8. 总结HashSet以及分析部分底层源码

    总结HashSet以及分析部分底层源码 1. HashSet继承的抽象类和实现的接口 继承的抽象类:AbstractSet 实现了Set接口 实现了Cloneable接口 实现了Serializabl ...

  9. LInkedList总结及部分底层源码分析

    LInkedList总结及部分底层源码分析 1. LinkedList的实现与继承关系 继承:AbstractSequentialList 抽象类 实现:List 接口 实现:Deque 接口 实现: ...

  10. Vector总结及部分底层源码分析

    Vector总结及部分底层源码分析 1. Vector继承的抽象类和实现的接口 Vector类实现的接口 List接口:里面定义了List集合的基本接口,Vector进行了实现 RandomAcces ...

随机推荐

  1. 揭秘10种主流PLC在ModbusTCP通信中的速度表现!

    大家好!我是付工. 通透!终于把ModbusRTU弄明白了 这样看来,ModbusTCP协议太简单了 太简单了!C#轻松实现Modbus通信 前面给大家介绍了一系列关于Modbus和ModbusTCP ...

  2. idea+maven打包.jar发布项目

    开发完项目后,idea+maven环境打包成.jar包,才能发布项目.下面记录常用的几种打包方式. 一,通过mvn命令打包 比较专业的用法是通过mvn命令打包: mvn clean package - ...

  3. Spaghetti pg walkthrough Intermediate

    nmap ┌──(root㉿kali)-[~] └─# nmap -p- -A 192.168.170.160 Starting Nmap 7.94SVN ( https://nmap.org ) a ...

  4. 『Python底层原理』--CPython 虚拟机

    在 Python 编程的世界里,我们每天都在使用 python 命令运行程序,但你是否曾好奇这背后究竟发生了什么? 本文将初步探究 CPython(Python 中最流行的实现)的一些内部机制,为了更 ...

  5. 云主机 vs 轻量型云主机:性能与灵活性的平衡

    本文分享自天翼云开发者社区<云主机 vs 轻量型云主机:性能与灵活性的平衡>,作者:冯****芙 什么是轻量型云主机.什么是云主机? 云主机是云计算的一种基础设施服务模型,它是在云平台上通 ...

  6. LangChain基础篇 (03)

    LangChain 核心模块学习:Memory 大多数LLM应用都具有对话界面.对话的一个重要组成部分是能够引用先前在对话中介绍过的信息.至少,一个对话系统应该能够直接访问一些过去消息的窗口.更复杂的 ...

  7. Handbook of Enumerative Combinatorics 阅读

    Chapter 1 代数几何方法 Part1 代数方法 1.3 生成函数 符号化方法和拉格朗日反演 拆分数的生成函数和五边形数定理.斐波那契的拆分数 平面二叉树(Plane Binary Tree). ...

  8. Flink基础Source配置

    一.pom文件 https://www.cnblogs.com/robots2/p/16048648.html 二.代码demo FlinkBaseSource.java package net.xd ...

  9. Kettle - 使用案例

    原文链接:https://blog.csdn.net/gdkyxy2013/article/details/117106691 案例一:把seaking的数据按id同步到seaking2,seakin ...

  10. swoole(7)php进程间通信-消息队列

    php实现消息队列操作 ftok:可以将一个路径转换成消息队列可用的key值 msg_get_queue:第一个参数是消息队列的key 第二个参数是消息队列的读写权限 server代码: <?p ...