一、release() 方法代码解析

当调用 release() 方法时,实际调用的是 AQS 的 releaseShared(1) 方法。以下是其详细工作流程:

 public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}

1、Semaphore.release()

public void release() {
sync.releaseShared(1); // 调用 AQS 的共享模式方法
}

2、AQS.releaseShared(int arg)

 public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) { // 尝试释放许可
doReleaseShared(); // 唤醒等待线程
return true;
}
return false;
}

3、Semaphore.tryReleaseShared(int releases)

protected boolean tryReleaseShared(int releases) {
for (;;) {
int current = getState(); // 当前剩余许可数
int next = current + releases; // 计算新的许可数
if (next < current) {
throw new Error("Maximum permit count exceeded"); // 防止溢出
}
if (compareAndSetState(current, next)) { // CAS 更新 state
return true; // 成功释放许可
}
}
}

4、AQS.doReleaseShared()

private void doReleaseShared() {
for (;;) {
Node h = head; // 获取队列头节点
if (h != null && h != tail) { // 队列不为空
int ws = h.waitStatus;
if (ws == Node.SIGNAL) { // 需要唤醒后继节点
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) {
continue; // CAS 失败,重试
}
unparkSuccessor(h); // 唤醒后继节点
} else if (ws == 0 && !compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) {
continue; // CAS 失败,重试
}
}
if (h == head) { // 头节点未变化,退出循环
break;
}
}
}

二、release() 的工作流程

当调用 release() 方法时,实际调用的是 AQS 的 releaseShared(1) 方法。以下是其详细工作流程:

(1)、增加许可数

1、调用 tryReleaseShared(arg):

  • tryReleaseShared(arg) 是 AQS 的模板方法,由 Semaphore 实现。

  • 在 Semaphore 中,tryReleaseShared(arg) 的逻辑是通过 int next = current + releases; 操作将 state 增加 1。

2、CAS 操作:

  • 使用 compareAndSetState(current, next) 方法原子性地更新 state 变量。

  • 如果 CAS 成功,表示线程成功释放许可;否则,重试。

(2)、唤醒等待线程

1、检查等待队列:

  • 如果 CLH 队列中有等待的线程,AQS 会唤醒队列中的第一个有效节点(线程)。

  • 被唤醒的线程会重新尝试获取许可。

2、传播唤醒:

  • 在共享模式下,AQS 会传播唤醒信号,确保所有等待的线程都有机会获取许可。

Semaphore.release()方法的底层原理的更多相关文章

  1. HashMap底层原理分析(put、get方法)

    1.HashMap底层原理分析(put.get方法) HashMap底层是通过数组加链表的结构来实现的.HashMap通过计算key的hashCode来计算hash值,只要hashCode一样,那ha ...

  2. KVO-基本使用方法-底层原理探究-自定义KVO-对容器类的监听

    书读百变,其义自见! 将KVO形式以代码实现呈现,通俗易懂,更容易掌握 :GitHub   -链接如果失效请自动搜索:https://github.com/henusjj/KVO_base 代码中有详 ...

  3. 红黑树规则,TreeSet原理,HashSet特点,什么是哈希值,HashSet底层原理,Map集合特点,Map集合遍历方法

    ==学习目标== 1.能够了解红黑树 2.能够掌握HashSet集合的特点以及使用(特点以及使用,哈希表数据结构) 3.能够掌握Map集合的特点以及使用(特点,常见方法,Map集合的遍历) 4.能够掌 ...

  4. 利用Redisson实现分布式锁及其底层原理解析

    Redis介绍 参考地址:https://blog.csdn.net/turbo_zone/article/details/83422215 redis是一个key-value存储系统.和Memcac ...

  5. iOS底层原理总结 - 探寻block的本质(一)

        面试题 block的原理是怎样的?本质是什么? __block的作用是什么?有什么使用注意点? block的属性修饰词为什么是copy?使用block有哪些使用注意? block在修改NSMu ...

  6. Java面试底层原理

    面试发现经常有些重复的面试问题,自己也应该学会记录下来,最好自己能做成笔记,在下一次面的时候说得有条不紊,深入具体,面试官想必也很开心.以下是我个人总结,请参考: HashSet底层原理:(问了大几率 ...

  7. Java8线程池ThreadPoolExecutor底层原理及其源码解析

    小侃一下 日常开发中, 或许不会直接new线程或线程池, 但这些线程相关的基础或思想是非常重要的, 参考林迪效应; 就算没有直接用到, 可能间接也用到了类似的思想或原理, 例如tomcat, jett ...

  8. 关于 ReentrantLock 中锁 lock() 和解锁 unlock() 的底层原理浅析

    关于 ReentrantLock 中锁 lock() 和解锁 unlock() 的底层原理浅析 如下代码,当我们在使用 ReentrantLock 进行加锁和解锁时,底层到底是如何帮助我们进行控制的啦 ...

  9. 【T-SQL进阶】02.理解SQL查询的底层原理

    本系列[T-SQL]主要是针对T-SQL的总结. [T-SQL基础]01.单表查询-几道sql查询题 [T-SQL基础]02.联接查询 [T-SQL基础]03.子查询 [T-SQL基础]04.表表达式 ...

  10. HashMap的底层原理

    简单说: 底层原理就是采用数组加链表: 两张图片很清晰地表明存储结构: 既然是线性数组,为什么能随机存取?这里HashMap用了一个小算法,大致是这样实现: // 存储时: int hash = ke ...

随机推荐

  1. 基于Redis组件的特性,实现一个分布式限流

    分布式---基于Redis进行接口IP限流 场景 为了防止我们的接口被人恶意访问,比如有人通过JMeter工具频繁访问我们的接口,导致接口响应变慢甚至崩溃,所以我们需要对一些特定的接口进行IP限流,即 ...

  2. Pycharm:鼠标滚动控制字体大小

    Pycharm字体放大的设置 1.File -> setting -> Keymap ->在搜寻框中输入:increase -> Increase Font Size(双击) ...

  3. Kotlin:【set集合】集合创建、可变集合mutableSetOf、集合转换(List转换成Set,去掉重复元素)、distinct快捷去重函数、数组

  4. uni-app封装网络请求

    在项目下创建一个文件夹https 然后在文件夹下面创建两个文件api.js request.js api.js 用于存放项目的请求接口 request.js 用于存放封装的请求接口get post 在 ...

  5. ThreeJs-13效果合成与后期处理

    一.合成效果原理与设置 什么是效果合成,就是可以把一些效果经过后期处理再放出来 原来的物体是直接通过render渲染出来,而现在则是经过一条render通道,可以处理也可以叠加处理后再放出来 首先正常 ...

  6. Idea报错 【cannot access com.xxx】的【解决办法】

    正常操作代码,一个类突然标红,提示 cannot access com.xxx . 执行下面操作,执行完后项目变为正常 但是如果是你代码存在异常,可不是清缓存就能解决了,就要靠自己了哈哈 第一步Fil ...

  7. [ZJOI2019] 语言 题解

    不愧是 \(ZJOI\),<最可做的一道题>都让人一头雾水-- 首先将问题转化到链上. 可以将总共的组数转化为每个点可以到达的城市. 明显给每个点建一棵动态开点线段树,维护可以和他通商的点 ...

  8. QT5笔记:7. 自定义类、自定义信号及类的元对象信息

    自定义的QPerson类,需要继承 QObject类 qperson.h头文件 #ifndef QPERSON_H #define QPERSON_H #include <QObject> ...

  9. zabbix - [03] 安装部署

    参考:https://www.yuque.com/fenghuo-tbnd9/ffmkvs zabbix6要求操作系统为Centos8,所以一开始安装部署的时候发现少了zabbix-server-my ...

  10. Sqoop - 使用场景

    Oracle >> HDFS sqoop import --connect jdbc:oracle:thin:@<oracle_host>:<oracle_port> ...