reentrantlock 是互斥锁,保证资源独占访问并要求同线程加锁/解锁;semaphore 是计数信号量,限制并发数量且允许不同线程获取/释放许可。

ReentrantLock 和 Semaphore 都是 Java 并发编程中基于 AQS 实现的核心同步工具,但它们解决的问题本质不同:一个管“谁有资格进”,一个管“最多能进几个”。
核心目的不同
ReentrantLock 是互斥锁,目标是保证某段代码或某个资源在同一时刻只能被一个线程访问。它强调“独占性”和“线程归属”——锁由哪个线程持有、必须由该线程释放。
Semaphore 是资源计数器,目标是限制同时使用某类资源的线程总数。它不追踪具体是谁拿了许可,只关心还剩几个可用。初始值设为 1 时行为类似锁,但这只是特例,不是设计本意。
状态模型与释放机制不同
ReentrantLock 的状态是二元的:已锁定 / 未锁定,背后维护着持有线程和重入次数。解锁必须由加锁线程执行,否则抛 IllegalMonitorStateException。
Semaphore 的状态是一个整型计数器(permits),acquire() 减一,release() 加一。任意线程都可以调用 release(),适合“获取者不一定是释放者”的场景,比如连接池中线程取连接、另一线程归还连接。
功能扩展能力不同
- ReentrantLock 支持多个 Condition 对象,可实现精准的线程等待/唤醒(如生产者-消费者中分别通知生产/消费线程)
- Semaphore 没有条件队列,只有基础的 acquire/release 操作,无法做细粒度协调
- ReentrantLock 提供 tryLock(timeout)、lockInterruptibly() 等增强控制能力,便于应对超时、中断等异常流程
- Semaphore 同样支持带超时的 tryAcquire,但不支持中断响应(除非用 tryAcquire(long, TimeUnit) 并配合手动检查中断)
典型适用场景不同
ReentrantLock 更适合保护临界区内的状态变更,例如:
- 更新共享变量(如账户余额、库存数量)
- 修改复杂对象内部结构(如链表插入、树节点调整)
- 需要条件等待的协作逻辑(如阻塞队列、线程安全的缓存刷新)
Semaphore 更适合控制资源池或并发上限,例如:
- 数据库连接池(限制最大活跃连接数)
- API 调用限流(每秒最多 100 次请求)
- 批量任务并发控制(同一时间最多执行 5 个异步导出任务)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











