AQS的release(int)方法底层源码

一、定义

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。


三、总结

posted @ 2025-02-28 11:38  jock_javaEE  阅读(38)  评论(0)    收藏  举报