Java 并发神器 Semaphore 深度剖析与源码整理

关键词:并发控制、限流、AQS、Semaphore、源码注释、流程图、业务场景


一、概述

在高并发、多线程开发场景下,资源限流与线程同步是系统稳定性和性能保障的核心。Java 并发包 java.util.concurrent 中的 Semaphore(信号量)类,就是解决这一问题的明星工具。它通过“许可”机制,优雅地控制同时访问共享资源的线程数量,广泛应用于数据库连接池、接口限流、分布式任务等场景。

本文将围绕 Semaphore 项目源码,展开全面校正与整理,结合结构化注释、主接口梳理、流程图与状态图、目录结构优化及业务场景结合说明,帮助开发者深入理解 Semaphore 的原理与最佳实践。


二、名词解释

  • Semaphore(信号量):一种并发控制机制,维护一组许可,线程获取许可后方能访问资源,许可不足则阻塞等待。
  • AQS(AbstractQueuedSynchronizer):Java 并发包的同步器抽象,底层队列与状态管理基石。
  • 公平/非公平模式:公平模式下,线程按先来先服务顺序获取许可;非公平模式则允许插队,提高吞吐但可能导致饥饿。
  • 许可(Permit):信号量的核心资源,代表可用访问次数。

三、项目背景与发展历史

Semaphore 作为并发控制的经典方案,最早由 Dijkstra 在 1965 年提出,成为操作系统与并发编程领域的基础工具。Java 在 JDK 1.5 引入了 java.util.concurrent 并发包,Semaphore 随之成为标准库成员。

  • 权威资料参考
    • Dijkstra, E. W. (1965). “Cooperating Sequential Processes”.
    • Doug Lea, “Concurrent Programming in Java: Design Principles and Patterns”, Addison Wesley, 2000.
    • 《Java 并发编程实战》(Brian Goetz 等著)
    • JDK Semaphore 官方文档

四、源码注释与主接口梳理

1. 核心源码详解

/**
 * Semaphore 并发信号量控制类
 * 用于限制指定数量线程同时访问共享资源
 */
public class Semaphore {
    // 内部同步器,基于 AQS 实现
    private final Sync sync;

    /**
     * 构造方法
     * @param permits 初始许可数量
     * @param fair 是否公平模式(true: 先来先服务)
     */
    public Semaphore(int permits, boolean fair) {
        sync = fair ? new FairSync(permits) : new NonfairSync(permits);
    }

    /**
     * 获取许可(阻塞直到获得)
     * @throws InterruptedException 可响应中断
     * 关键逻辑:原子减 state,许可不足则入队列阻塞
     * 速记口诀:获取原子减,阻塞入队列
     */
    public void acquire() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

    /**
     * 释放许可
     * 关键逻辑:原子加 state,唤醒阻塞队列线程
     * 速记口诀:释放原子加,唤醒重试获
     */
    public void release() {
        sync.releaseShared(1);
    }

    /**
     * 查询当前可用许可数
     * @return 当前剩余许可
     */
    public int availablePermits() {
        return sync.getPermits();
    }
    // ...其他方法省略
}
主流程接口梳理
接口/类 作用说明 调用顺序 备注
Semaphore 信号量主入口类,管理许可和同步队列 提供 acquire/release 等主流程接口
acquire() 获取许可,阻塞直到成功 限流入口,常用于资源访问前
release() 释放许可,唤醒阻塞线程 资源访问结束时调用
availablePermits() 查询当前剩余许可数 任意 可用于监控与业务限流判断
Sync/FairSync/NonfairSync 内部同步器,管理许可和队列状态 内部 继承 AQS,负责底层同步机制

五、结构化流程图解读

1. 主流程结构优化(flowchart)

flowchart TD
    A[初始化 Semaphore] --> B[线程请求 acquire]
    B --> C{许可是否足够?}
    C -- 是 --> D[许可减1,进入临界区]
    C -- 否 --> E[入队列阻塞]
    D --> F[执行任务]
    F --> G[release 释放许可]
    G --> H[许可加1,唤醒队列线程]
    H --> B
    E --> H

简化说明

  • 初始化 Semaphore,设定最大并发数
  • 线程获取许可,不足则自动排队阻塞
  • 任务结束释放许可,自动唤醒队列

2. 状态流转优化(stateDiagram-v2)

许可足够
许可不足
许可释放
等待许可
获取许可
执行任务
队列阻塞
被唤醒
释放许可

简化说明

  • 线程状态在“等待许可”、“执行任务”、“队列阻塞”、“被唤醒”之间流转
  • 资源释放后,阻塞线程被唤醒重新竞争许可

3. 关键交互序列图优化(sequenceDiagram)

线程1 Semaphore 队列 acquire() state--, 获取许可 release() 唤醒阻塞线程 入队阻塞 挂起等待 release()触发唤醒 重新尝试获取 alt [许可充足] [许可不足] 线程1 Semaphore 队列

简化说明

  • 线程获取许可时,Semaphore 判断是否足够
  • 不足则队列挂起,释放后自动唤醒重试

六、目录结构优化建议

推荐目录结构如下:

src/
 main/
    java/
       com/example/semaphore/
          Semaphore.java         // 主流程入口类,核心信号量实现
          Sync.java              // 内部同步器,AQS封装
          FairSync.java          // 公平同步器实现
          NonfairSync.java       // 非公平同步器实现
          SemaphoreTest.java     // 单元测试/示例
          utils/
               ThreadUtils.java  // 通用线程工具
    resources/
        application.properties     // 配置文件
 docs/
    Semaphore原理与应用.md          // 核心原理文档
    diagrams/                     // 流程图/状态图/序列图
  • 主流程入口:Semaphore.java
  • 同步队列管理:Sync、FairSync、NonfairSync
  • 单元测试/示例:SemaphoreTest.java
  • 工具模块:utils 目录
  • 文档与流程图:docs 目录,便于团队协作与知识沉淀

七、业务场景结合说明

1. 连接池限流

// 获取数据库连接前,限流保护
try {
    semaphore.acquire(); // 限流入口,防止连接数超标
    Connection conn = pool.getConnection();
    // ...业务处理
} finally {
    semaphore.release(); // 释放许可,允许后续线程获取连接
}

2. 接口限流

// API高并发限流
semaphore.acquire(); // 限流入口,超限自动排队
// 处理请求
semaphore.release(); // 释放许可,唤醒阻塞线程

3. 分布式任务调度

每台机器最多并发 50 个爬虫任务,Semaphore(50) 控制线程数量,保障带宽与资源。


八、速记口诀与系统性认知总结

Semaphore 速记口诀

  • 初始化设许可:根据资源上限,准确配置许可数
  • 获取原子减:每次访问资源前,原子性扣减许可
  • 阻塞入队列:超限自动排队,避免资源争抢
  • 释放原子加:资源释放后,原子性恢复许可
  • 唤醒重试获:唤醒阻塞线程,公平竞争许可

系统性认知
Semaphore 是并发限流的基石。知其然,需理解源码与流程。知其所以然,需结合 AQS 队列、主流程接口、状态流转与实际业务场景。通过流程图、状态图、序列图,结构化理解 Semaphore 的核心机制,能在高并发系统中合理限流、保障稳定。


九、参考文献

  1. Dijkstra, E. W. (1965). “Cooperating Sequential Processes”.
  2. Doug Lea, “Concurrent Programming in Java: Design Principles and Patterns”, Addison Wesley, 2000.
  3. Brian Goetz 等, 《Java 并发编程实战》
  4. JDK Semaphore 官方文档
  5. AQS 原理解析

知其然,更要知其所以然!
通过结构化注释、流程图、目录优化、业务场景结合,Semaphore 源码更加易懂、实用、可维护。建议在实际项目中严格限流,保障系统高并发下的稳定性与性能。

更多推荐