【锁3】Semaphore(信号量)

📅 2026/8/1 14:00:22
【锁3】Semaphore(信号量)
Semaphore信号量的核心是用 N 张“许可证”限制同时访问资源的线程数——线程进来先 acquire() 拿一张用完 release() 还回去许可证发完了后面的线程就得排队。下面给你 Java 最常用版本的可运行示例。核心概念初始化时指定许可证数量 N相当于“最多允许 N 个线程同时进临界区”acquire()拿许可证没有就阻塞等待release()还许可证务必放在finally或使用with否则忘了释放就会死锁tryAcquire()非阻塞版本拿不到立刻返回false适合做限流降级importjava.util.concurrent.Semaphore;publicclassSemaphoreDemo{// 许可证数量为 3即同时最多 3 个线程能进临界区privatestaticfinalSemaphoresemaphorenewSemaphore(3);publicstaticvoidmain(String[]args){for(inti1;i5;i){newThread(newTask(线程-i)).start();}}staticclassTaskimplementsRunnable{privatefinalStringname;Task(Stringname){this.namename;}Overridepublicvoidrun(){try{semaphore.acquire();// 拿许可证没有就阻塞System.out.println(name 进入临界区当前可用许可证: semaphore.availablePermits());Thread.sleep(2000);// 模拟业务耗时System.out.println(name 执行完毕);}catch(InterruptedExceptione){e.printStackTrace();}finally{semaphore.release();// 一定要释放System.out.println(name 释放许可证);}}}}运行后会看到前 3 个线程同时进入后 2 个等前面有人释放后才依次进入。线程-1 进入临界区当前可用许可证:2线程-4 进入临界区当前可用许可证:0线程-3 进入临界区当前可用许可证:1线程-1 执行完毕 线程-4 执行完毕 线程-3 执行完毕 线程-4 释放许可证 线程-3 释放许可证 线程-1 释放许可证 线程-5 进入临界区当前可用许可证:1线程-2 进入临界区当前可用许可证:2线程-5 执行完毕 线程-5 释放许可证 线程-2 执行完毕 线程-2 释放许可证 进程已结束退出代码为0 典型应用场景对比场景许可证数量说明数据库连接池连接数上限例如设置 10防止连接耗尽API 接口限流QPS 上限例如设置 50保护后端服务爬虫并发控制目标站承受力避免请求过快被封 IP互斥锁Mutex*1等同于Lock实现线程独占⚠️ 注意事项死锁风险如果acquire()后未调用release()如异常中断会导致永久阻塞。公平性Java 构造器new Semaphore(3, true)可设置为公平模式FIFO但会降低性能。Asyncio 作用域asyncio.Semaphore必须在async def函数内创建不能在模块顶层创建会报 Event Loop 错误。