Java并发编程中Semaphore有什么作用

来源:IT编程作者:相泽南头衔:网络博主
导读:本期聚焦于小伙伴创作的《Java并发编程中Semaphore有什么作用》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Java并发编程中Semaphore有什么作用》有用,将其分享出去将是对创作者最好的鼓励。

Semaphore的核心作用

Semaphore是Java并发包java.util.concurrent下的一个同步工具类,它的核心作用是控制同时访问某个特定资源的线程数量,或者同时执行某个指定操作的线程数量。它内部维护了一个许可证集合,线程在访问资源前需要先获取许可证,访问完成后释放许可证,当许可证不足时,线程会被阻塞等待。

Java并发编程中Semaphore有什么作用

Semaphore的常见使用场景包括:限制数据库连接池的并发访问数量、控制接口的请求并发量、实现停车场车位管理等有限资源管控场景。和synchronized、ReentrantLock这类互斥锁不同,Semaphore允许指定数量的线程同时访问资源,属于共享锁的一种实现。

Semaphore的构造方法

Semaphore提供了两个常用的构造方法,分别用于指定初始许可证数量和是否使用公平策略:

import java.util.concurrent.Semaphore;

public class SemaphoreDemo {
    public static void main(String[] args) {
        // 初始化3个许可证,非公平模式
        Semaphore semaphore = new Semaphore(3);
        // 初始化3个许可证,公平模式,按线程等待顺序分配许可证
        Semaphore fairSemaphore = new Semaphore(3, true);
    }
}

Semaphore的资源控制模型

Semaphore的底层是基于AbstractQueuedSynchronizer(AQS)实现的,它的资源控制模型可以拆解为三个核心部分:许可证管理、线程阻塞队列、获取释放逻辑。

许可证管理机制

Semaphore的许可证数量本质就是AQS中的state变量,初始化时设置state的值为指定的许可证数量。当线程调用acquire()方法时,会尝试对state执行减1操作,如果减1后state大于等于0,说明获取许可证成功;如果state小于0,说明许可证不足,线程会被加入AQS的等待队列中阻塞。

当线程调用release()方法时,会对state执行加1操作,同时唤醒等待队列中头部的线程,被唤醒的线程会再次尝试获取许可证。

公平与非公平模式差异

Semaphore支持公平和非公平两种模式,两种模式的差异主要体现在许可证分配逻辑上:

  • 非公平模式:线程获取许可证时直接尝试修改state,不会检查等待队列中是否有其他线程在等待,可能出现后到的线程先获取许可证的情况,吞吐量更高。
  • 公平模式:线程获取许可证前会先检查AQS等待队列中是否有前驱节点,如果有则直接加入队列等待,严格按照线程等待顺序分配许可证,避免线程饥饿,但性能略低。

核心方法说明

Semaphore提供了多个重载的方法用于获取和释放许可证,常用方法如下:

方法名作用说明
acquire()获取1个许可证,若许可证不足则阻塞当前线程
acquire(int permits)获取指定数量的许可证,若许可证不足则阻塞当前线程
tryAcquire()尝试获取1个许可证,获取成功返回true,失败立即返回false,不阻塞线程
tryAcquire(long timeout, TimeUnit unit)尝试在指定时间内获取1个许可证,超时未获取则返回false
release()释放1个许可证,唤醒等待队列中的线程
release(int permits)释放指定数量的许可证
availablePermits()返回当前可用的许可证数量

Semaphore使用示例

下面通过一个模拟停车场车位的示例来演示Semaphore的实际使用,假设停车场有3个车位,10辆车依次尝试进入停车场:

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class ParkingLotDemo {
    // 停车场有3个车位
    private static final Semaphore PARKING_SPOTS = new Semaphore(3);

    public static void main(String[] args) {
        // 模拟10辆车进入停车场
        for (int i = 1; i <= 10; i++) {
            int carId = i;
            new Thread(() -> {
                try {
                    System.out.println("车辆" + carId + "尝试进入停车场");
                    // 获取1个车位许可证
                    PARKING_SPOTS.acquire();
                    System.out.println("车辆" + carId + "成功进入停车场,当前剩余车位:" + PARKING_SPOTS.availablePermits());
                    // 模拟停车时间
                    TimeUnit.SECONDS.sleep(2);
                    // 释放车位许可证
                    PARKING_SPOTS.release();
                    System.out.println("车辆" + carId + "离开停车场,当前剩余车位:" + PARKING_SPOTS.availablePermits());
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    System.out.println("车辆" + carId + "进入停车场被中断");
                }
            }, "车辆线程-" + i).start();
        }
    }
}

运行上述代码可以看到,同一时间最多只有3辆车能进入停车场,其余车辆需要等待已有车辆离开释放车位后才能进入,完美实现了有限资源的并发控制。

使用注意事项

在使用Semaphore时需要注意以下几点:

  • 获取许可证的数量和释放的数量需要保持一致,如果获取了多个许可证但只释放部分,会导致许可证数量不断减少,最终所有线程都无法获取许可证。
  • 如果线程被中断,acquire()方法会抛出InterruptedException,需要根据业务场景合理处理中断逻辑。
  • 公平模式虽然能避免线程饥饿,但会增加线程上下文切换的开销,非必要场景下建议使用非公平模式提升性能。
  • Semaphore的许可证数量可以动态修改,但是修改后不会影响已经在等待队列中的线程的唤醒顺序。
Semaphore是Java并发编程中非常实用的资源控制工具,合理使用它可以有效避免多线程场景下资源过载的问题,同时也能实现灵活的线程同步逻辑,开发者需要根据实际业务场景选择合适的模式和参数配置。

SemaphoreJava并发编程资源控制信号量线程同步修改时间:2026-07-14 06:51:34

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