深入理解 Semaphore 【源码分析】

本文介绍了Semaphore的基本概念,它是如何通过AQS实现并发控制的,包括acquire(),release(),tryAcquire(),和doAcquireSharedInterruptibly等方法的工作原理。特别关注了Semaphore在控制并发量、限流场景中的应用实例和常见方法的源码分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Semaphore

Semaphore 是信号量的意思,一般用来控制同时访问某个资源的线程数量,协调各个线程合理的访问公共资源,Semaphore 的底层依赖的是 AQS。
Semaphore 使用计数器来控制对共享资源的访问, 如果计数器大于0,则表示允许访问共享资源, 如果为 0,则表示共享资源已经达到访问的上限就拒绝访问, 计数器的计数的就是允许同时访问共享资源的线程数。

知识储备传送门:

深入理解 AbstractQueuedSynchronizer(AQS)【源码分析】
深入理解 ReentrantLock 【源码分析】
CAS的使用以及底层原理详解
深入理解 CountDownLatch 【源码分析】

Semaphore 的应用场景:

控制并发量,通常用于那些资源有明确访问数量限制的场景,常用于限流 ,比如停车场场景,停车场内部车位有限,同时只能停有限车辆,比如窗口办业务场景,窗口有限,同时只能有限的人同时办业务。

Semaphore 使用简单举例:

public static void main(String[] args) {
   
        Semaphore semaphore = new Semaphore(2);
        for (int a = 0; a < 4; a++) {
   
            new Thread(() -> {
   
                try {
   
                    semaphore.acquire();
                    System.out.println("当前线程获取许可,线程名称:" + Thread.currentThread().getName() + ";当前时间:" + System.currentTimeMillis() / 1000);
                    Thread.sleep(2000);
                    semaphore.release();
                    System.out.println("当前线程释放许可,线程名称:" + Thread.currentThread().getName() + ";当前时间:" + System.currentTimeMillis() / 1000);
                } catch (InterruptedException e) {
   
                    e.printStackTrace();
                }
                System.out.println();
            }).start();
        }
    }

执行结果:

当前线程获取许可,线程名称:Thread-0;当前时间:1712322271
当前线程获取许可,线程名称:Thread-1;当前时间:1712322271
当前线程释放许可,线程名称:Thread-0;当前时间:1712322273
当前线程获取许可,线程名称:Thread-3;当前时间:1712322273
当前线程获取许可,线程名称:Thread-2;当前时间:1712322273
当前线程释放许可,线程名称:Thread-1;当前时间:1712322273
当前线程释放许可,线程名称:Thread-2;当前时间:1712322275
当前线程释放许可,线程名称:Thread-3;当前时间:1712322275

执行结果分析:

我们的案例代码是想同时启动 4 个线程,Semaphore 只有两个信号量,我们发现 1712322271 时候,有两个线程获取了许可,执行了业务代码,1712322273 时刻有两个线程释放了许可,同时另外两个线程才获取到许可,开始执行业务代码,达到了使用 Semaphore 信号量控制并发的目的。

Semaphore 常用方法:

  • acquire() :获取一个执行许可,在获取到执行许可之前或者被其他线程中断之前,线程一直会被阻塞。
  • acquire(int permits) :获取 permits 个执行许可,在获取到执行许可之前或者被其他线程中断之前,线程一直会被阻塞。
  • acquireUninterruptibly() :获取一个执行许可,在获取到执行许可之前(忽略中断),线程一直会被阻塞。
  • tryAcquire() :尝试获取一个执行许可,返回获取的结果,线程不会
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值