导读:本期聚焦于小伙伴创作的《如何通过 AQS 的 state 变量理解 Semaphore 与 CountDownLatch 的共享锁实现》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《如何通过 AQS 的 state 变量理解 Semaphore 与 CountDownLatch 的共享锁实现》有用,将其分享出去将是对创作者最好的鼓励。

AQS即AbstractQueuedSynchronizer,是Java并发包中构建锁和同步器的核心框架,其内部维护的state变量是一个volatile修饰的整型值,不同的同步工具通过操作这个变量实现各自的同步逻辑。Semaphore和CountDownLatch都采用了AQS的共享锁模式,二者的功能差异本质上是对state变量的定义和操作方式不同。

如何通过 AQS 的 state 变量理解 Semaphore 与 CountDownLatch 的共享锁实现

AQS共享锁与state变量的基础逻辑

AQS的共享锁模式下,多个线程可以同时获取锁,核心的判断逻辑围绕state变量展开。共享锁的获取和释放会分别调用tryAcquireSharedtryReleaseShared方法,这两个方法的具体实现由基于AQS的同步工具类自定义,而state变量就是这两个方法操作的核心对象。

当线程尝试获取共享锁时,会调用tryAcquireShared方法,方法的返回值决定了获取结果:返回负数表示获取失败,返回0表示获取成功但没有剩余资源,返回正数表示获取成功且还有剩余资源可以供其他线程获取。当线程释放共享锁时,会调用tryReleaseShared方法,返回true表示释放成功,可能会唤醒后续等待的线程。

Semaphore中state变量的作用

Semaphore的中文含义是信号量,它的作用是控制同时访问特定资源的线程数量,其底层就是通过AQS的共享锁实现的,state变量在这里表示可用的许可证数量。

Semaphore的初始化与state赋值

创建Semaphore对象时,需要传入初始的许可证数量,这个数量会直接赋值给AQS的state变量。比如我们创建一个有3个许可证的Semaphore:

import java.util.concurrent.Semaphore;

public class SemaphoreDemo {
    public static void main(String[] args) {
        // 初始化3个许可证,此时AQS的state值为3
        Semaphore semaphore = new Semaphore(3);
    }
}

获取许可证时的state操作

当线程调用acquire方法获取许可证时,Semaphore的tryAcquireShared方法会尝试将state值减1。如果减1后的结果大于等于0,说明还有可用许可证,获取成功;如果结果小于0,说明没有可用许可证,当前线程会被加入AQS的等待队列中阻塞。

下面是简化后的获取逻辑代码示例:

// Semaphore内部Sync类的tryAcquireShared简化实现
protected int tryAcquireShared(int acquires) {
    for (;;) {
        int available = getState();
        int remaining = available - acquires;
        // 如果剩余数量小于0,或者CAS更新state成功,返回结果
        if (remaining < 0 ||
            compareAndSetState(available, remaining))
            return remaining;
    }
}

释放许可证时的state操作

当线程调用release方法释放许可证时,Semaphore的tryReleaseShared方法会将state值加1,然后唤醒等待队列中阻塞的线程尝试获取许可证。

简化后的释放逻辑代码示例:

// Semaphore内部Sync类的tryReleaseShared简化实现
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))
            return true;
    }
}

CountDownLatch中state变量的作用

CountDownLatch的作用是让一个或多个线程等待其他线程完成操作后再继续执行,它同样基于AQS的共享锁实现,state变量在这里表示需要等待的任务数量。

CountDownLatch的初始化与state赋值

创建CountDownLatch对象时,需要传入一个计数值,这个计数值会直接赋值给AQS的state变量。比如我们创建一个计数值为5的CountDownLatch:

import java.util.concurrent.CountDownLatch;

public class CountDownLatchDemo {
    public static void main(String[] args) {
        // 初始化计数值为5,此时AQS的state值为5
        CountDownLatch latch = new CountDownLatch(5);
    }
}

await方法对应的state操作

当线程调用await方法时,CountDownLatch的tryAcquireShared方法会检查state的值。如果state等于0,说明所有任务都已完成,返回1表示获取成功;如果state不等于0,返回-1表示获取失败,当前线程会被加入AQS等待队列阻塞。

简化后的await逻辑代码示例:

// CountDownLatch内部Sync类的tryAcquireShared简化实现
protected int tryAcquireShared(int acquires) {
    return (getState() == 0) ? 1 : -1;
}

countDown方法对应的state操作

当线程调用countDown方法时,CountDownLatch的tryReleaseShared方法会将state值减1。如果减1后state等于0,说明所有任务都已完成,返回true唤醒等待队列中阻塞的线程;如果减1后state仍大于0,返回false。

简化后的countDown逻辑代码示例:

// CountDownLatch内部Sync类的tryReleaseShared简化实现
protected boolean tryReleaseShared(int releases) {
    for (;;) {
        int c = getState();
        if (c == 0)
            return false;
        int nextc = c - 1;
        if (compareAndSetState(c, nextc))
            return nextc == 0;
    }
}

二者的state变量使用差异对比

虽然Semaphore和CountDownLatch都基于AQS共享锁实现,但state变量的使用逻辑有明显差异,具体对比如下:

对比维度SemaphoreCountDownLatch
state变量含义可用许可证数量待完成的任务数量
获取锁时state变化state减1,大于等于0则获取成功state不变,等于0则获取成功
释放锁时state变化state加1,唤醒等待线程state减1,减到0时唤醒等待线程
state是否可重复增长是,释放许可证会增长否,只能递减到0

总结

通过state变量的逻辑可以清晰区分Semaphore和CountDownLatch的底层实现:Semaphore的state是可用资源数,获取时减少、释放时增加,支持多个线程同时获取资源;CountDownLatch的state是剩余任务数,只有递减到0时才能让等待线程继续执行,且state只会递减不会增长。理解state变量的作用,不仅能掌握这两个工具类的底层原理,也能更好地体会AQS框架的扩展性设计思路。

AQSstate_变量SemaphoreCountDownLatch共享锁修改时间:2026-06-28 19:51:34

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。