首页 游戏 软件 资讯 排行榜 专题
首页
业界动态
Semaphore 限流器源码解析 AQS 共享模式实现原理详解

Semaphore 限流器源码解析 AQS 共享模式实现原理详解

热心网友
18
转载
2026-05-14

各位Java开发者,在上一篇深入解析AQS独占模式与ReentrantLock之后,我们已经掌握了处理“互斥访问”的核心技术。然而,在实际的高并发系统设计与性能优化中,仅仅实现互斥是远远不够的。我们经常需要更精细的并发控制能力——精确管理同一时刻能够访问特定资源的线程数量。无论是实现API限流、数据库连接池管理、还是控制并行任务执行数量,这些场景都需要一种更强大的并发控制机制。

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈

这一切功能背后的技术基石,正是AQS的共享模式。它是Semaphore(信号量)、CountDownLatch(倒计时器)、CyclicBarrier(循环屏障)等Java并发工具类的通用底层架构。理解AQS共享模式的工作原理,是掌握Java高并发编程的关键一步。

一、核心区别:AQS独占模式与共享模式对比

要快速理解两者的本质差异,只需记住这一句话:

  • 独占模式(Exclusive Mode):资源具有排他性,同一时刻仅允许一个线程持有。典型实现是ReentrantLock可重入锁。
  • 共享模式(Shared Mode):资源具有可共享性,允许多个线程同时持有。Semaphore信号量、CountDownLatch等工具都基于此模式构建。

二、AQS共享模式核心架构(基于JDK8源码)

首先查看AQS中支持共享模式的关键字段定义:

public abstract class AbstractQueuedSynchronizer {
    // 共享状态:多个线程可以同时访问和修改
    private volatile int state;
    // CLH同步队列头尾指针
    private transient volatile Node head;
    private transient volatile Node tail;
}

共享模式的设计思想非常直观易懂:

  • state字段在此模式下代表“可用资源的总数量”。
  • 线程申请资源时,通过CAS操作将state值减1;释放资源时,将state值加1。
  • 只要state > 0,就表示还有可用资源,允许多个线程并发获取。

三、AQS共享模式核心源码深度解析

1. 核心入口方法:acquireShared(int arg)

public final void acquireShared(int arg) {
    if (tryAcquireShared(arg) < 0) {
        // 获取资源失败 → 进入同步队列等待
        doAcquireShared(arg);
    }
}

这个方法有几个关键设计要点:

  • tryAcquireShared是模板方法,由具体的子类(如Semaphore、CountDownLatch)实现其具体逻辑。
  • 返回值语义:返回值≥0表示获取资源成功;返回值<0则表示获取失败,当前线程需要进入同步队列等待。

2. 核心逻辑:doAcquireShared入队与阻塞机制

private void doAcquireShared(int arg) {
    final Node node = addWaiter(Node.SHARED);
    boolean failed = true;
    try {
        boolean interrupted = false;
        for (;;) {
            final Node p = node.predecessor();
            if (p == head) {
                // 再次尝试获取共享资源
                int r = tryAcquireShared(arg);
                if (r >= 0) {
                    // 获取成功 → 传播唤醒后续的共享节点
                    setHeadAndPropagate(node, r);
                    p.next = null;
                    if (interrupted)
                        selfInterrupt();
                    failed = false;
                    return;
                }
            }
            // 检查并执行线程阻塞
            if (shouldParkAfterFailedAcquire(p, node) &&
                parkAndCheckInterrupt())
                interrupted = true;
        }
    } finally {
        if (failed)
            cancelAcquire(node);
    }
}

共享模式最显著的特征就体现在这里:唤醒传播机制(propagation)。当一个共享节点被唤醒并成功获取资源后,它会通过setHeadAndPropagate方法,主动尝试唤醒同步队列中后续的所有共享节点。这种设计实现了“连锁唤醒”效果,让多个等待线程能够高效地批量恢复执行,极大提升了并发性能。

3. 资源释放:releaseShared方法

public final boolean releaseShared(int arg) {
    if (tryReleaseShared(arg)) {
        // 释放成功 → 唤醒队列中的等待节点
        doReleaseShared();
        return true;
    }
    return false;
}

这里的doReleaseShared方法是AQS共享模式唤醒机制的核心。它通过循环检查和传播唤醒的算法,确保所有在同步队列中等待的共享线程都能被正确、高效地唤醒,避免了“唤醒丢失”问题。

四、Semaphore源码深度剖析(限流核心工具)

Semaphore是AQS共享模式最经典的应用实现,它的核心功能是控制最多N个线程同时访问特定资源。

1. Semaphore内部结构(JDK8实现)

public class Semaphore {
    private final Sync sync;

    abstract static class Sync extends AbstractQueuedSynchronizer {
        Sync(int permits) {
            setState(permits); // permits = 初始许可证数量
        }
    }

    // 非公平同步器(默认实现)
    static final class NonfairSync extends Sync {
        protected int tryAcquireShared(int acquires) {
            return nonfairTryAcquireShared(acquires);
        }
    }

    // 公平同步器
    static final class FairSync extends Sync {
        protected int tryAcquireShared(int acquires) {
            // 先检查同步队列,再尝试获取
        }
    }
}

2. 核心逻辑:非公平模式获取许可证

final int nonfairTryAcquireShared(int acquires) {
    for (;;) {
        int a vailable = getState();
        int remaining = a vailable - acquires;
        if (remaining < 0 ||
            compareAndSetState(a vailable, remaining))
            return remaining;
    }
}

这段代码的逻辑清晰明了:

  1. 获取当前可用许可证数量(从state字段读取)。
  2. 计算获取指定数量后的剩余许可证(remaining = state - acquires)。
  3. 如果remaining ≥ 0且CAS设置状态成功,则获取成功。
  4. 如果remaining < 0,则获取失败,线程将进入AQS同步队列等待。

3. 许可证释放实现

protected final boolean tryReleaseShared(int releases) {
    for (;;) {
        int current = getState();
        int next = current + releases;
        if (compareAndSetState(current, next))
            return true;
    }
}

释放操作本质上是增加state值(可用许可证数量),然后通过AQS的doReleaseShared方法唤醒同步队列中等待的线程,让它们有机会获取新释放的资源。

五、公平信号量与非公平信号量对比

这是使用Semaphore时需要理解的重要选择:

  • 非公平模式(默认):线程获取许可证时,会先直接尝试CAS抢占,抢不到再进入队列等待。这种方式减少了线程切换开销,吞吐量更高。
  • 公平模式:线程获取许可证前,会先检查AQS同步队列中是否有其他线程在等待。如果有,则自己必须入队等待,严格遵循先来后到的顺序,避免了线程“饥饿”问题。

对于大多数业务场景,使用默认的非公平模式即可获得最佳性能。只有在需要严格保证公平性的特殊场景下,才需要考虑使用公平模式。

六、Semaphore实战应用场景(可直接落地)

理解了Semaphore的实现原理,我们来看看它在实际系统中的典型应用:

  • API接口限流:限制某个关键接口同时处理的请求数不超过预设阈值(如20个)。
  • 数据库连接池控制:管理访问数据库连接等稀缺资源的并发数量。
  • 多线程任务流速控制:防止瞬间提交大量任务导致线程池过载,实现平滑的任务处理。
  • 系统资源访问控制:控制同时访问文件、网络连接等系统资源的线程数量。

标准的使用模板如下,务必注意在finally块中释放许可证,避免资源泄漏:

Semaphore semaphore = new Semaphore(20);
try {
    semaphore.acquire();  // 获取许可证
    // 执行受保护的业务逻辑
} finally {
    semaphore.release();  // 必须释放许可证
}

七、Java并发体系完整串联

至此,我们可以将JUC并发工具包的核心脉络完整串联起来:

  • ReentrantLock → 基于AQS独占模式,解决资源互斥访问问题。
  • Semaphore → 基于AQS共享模式,解决资源数量控制与限流问题。
  • CountDownLatch → 同样是AQS共享模式的应用(state减到0时唤醒所有等待线程)。
  • CyclicBarrier → 基于ReentrantLock和Condition实现,解决线程同步等待问题。
  • ThreadPoolExecutor → 其内部的工作线程控制、状态管理也大量运用了AQS的设计思想。

掌握了AQS的独占与共享这两种核心模式,意味着你已经打通了Java并发编程最底层的技术逻辑。这不仅能够帮助你深入理解JUC中各种并发工具的实现原理,更能让你在实际开发中设计出更高效、更稳定的并发控制系统。

来源:https://www.51cto.com/article/843074.html
免责声明: 游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

最新APP

宝宝过生日
宝宝过生日
应用辅助 04-07
台球世界
台球世界
体育竞技 04-07
解绳子
解绳子
休闲益智 04-07
骑兵冲突
骑兵冲突
棋牌策略 04-07
三国真龙传
三国真龙传
角色扮演 04-07

热门推荐

清华大学AI视觉模型推理能力深度评测报告
AI
清华大学AI视觉模型推理能力深度评测报告

这项由清华大学、美团、香港大学等多家顶尖机构联合开展的研究,于2026年3月以预印本论文(arXiv:2603 25823v1)的形式发布。它直指当前AI视觉生成领域一个被长期忽视的核心问题:这些能画出“神作”的模型,到底有多“聪明”?研究团队为此构建了一套全新的测试基准——ViGoR-Bench,

热心网友
05.14
AI科学写作新突破:机器自动生成完整学术论文
AI
AI科学写作新突破:机器自动生成完整学术论文

人工智能的浪潮席卷了各个领域,机器在诸多任务上已展现出超越人类的能力。然而,有一个看似寻常却异常复杂的领域,始终是AI研究者们渴望攻克的堡垒——让机器像真正的学者那样,撰写出一篇结构严谨、逻辑自洽、图文并茂的完整科学论文。这远比下棋或识图要困难得多。 2026年3月,一项由中科院AgentAlpha

热心网友
05.14
法国Hornetsecurity与里尔大学合作:AI隐私保护技术从675亿到1.5亿参数的知识迁移实践
AI
法国Hornetsecurity与里尔大学合作:AI隐私保护技术从675亿到1.5亿参数的知识迁移实践

这项由法国Hornetsecurity公司与里尔大学、法国国家信息与自动化研究院(Inria)、法国国家科学研究中心(CNRS)以及里尔中央理工学院联合开展的研究,发表于2026年3月31日的计算机科学期刊,论文编号为arXiv:2603 29497v1。 在信息爆炸的今天,我们每天都在网上留下数字

热心网友
05.14
清华大学AI自主编写操作指南研究突破人工编程局限
AI
清华大学AI自主编写操作指南研究突破人工编程局限

当你满怀期待地拆开一台全新的智能设备,最令人困扰的往往不是如何使用它,而是如何让它真正“理解”指令并智能地执行任务。如今,一个更为优雅的解决方案可能已经出现。来自清华大学深圳国际研究生院与哈尔滨工业大学(深圳)的联合研究团队,近期取得了一项极具前瞻性的突破:他们成功训练人工智能自主“撰写”并精准理解

热心网友
05.14
华盛顿大学AI新突破图片转可编辑矢量图形技术详解
AI
华盛顿大学AI新突破图片转可编辑矢量图形技术详解

2026年3月,来自华盛顿大学、艾伦人工智能研究所和北卡罗来纳大学教堂山分校的研究团队,在图像智能矢量化领域取得了一项突破性进展。这项研究(论文编号:arXiv:2603 24575v1)开发了一个名为VFig的AI系统,它能够将静态的栅格图像智能地转换为可自由编辑的矢量图形,如同一位“图形考古学家

热心网友
05.14