reentrantlock 的 trylock() 通过 cas 直接操作 state 字段实现毫秒级非阻塞加锁,不入 aqs 队列;公平锁下仍“插队”尝试;trylock(long, timeunit) 则会入队并限时等待;使用时须配 unlock() 且适用于轮询、避阻塞等场景。

ReentrantLock 的 tryLock() 能实现毫秒级非阻塞加锁,关键在于它绕过了 AQS 队列的入队/唤醒开销,直接用 CAS 原子操作尝试获取锁状态。
底层基于 state 字段的 CAS 尝试
tryLock() 不会调用 acquire() 或进入 AQS 同步队列,而是直接对 state 字段做一次 CAS 比较并交换:
- 若当前
state == 0(锁空闲),则 CAS 设置为 1,成功返回true - 若
state != 0,说明已被占用(可能重入或被其他线程持有),立即返回false - 该过程不修改 AQS 的
head/tail、不创建 Node、不挂起线程,纯用户态原子指令
公平锁与非公平锁在 tryLock 中行为一致
无论构造时是否启用公平模式(new ReentrantLock(true)),tryLock() 都不检查等待队列:
- 公平锁的“公平性”只影响
lock()(即阻塞式获取)时是否排队; -
tryLock()始终是“插队式”尝试——只要锁空闲就抢,不管队列里有没有人等着; - 所以
tryLock()在公平锁下也不保证 FIFO,这是设计使然,也是性能来源。
可中断版本 tryLock(long, TimeUnit) 的特殊处理
tryLock(timeout, unit) 表现不同:它先尝试一次快速 CAS,失败后会进入 AQS 的限时等待逻辑:
- 构造一个
Node加入同步队列尾部; - 调用
LockSupport.parkNanos()进行纳秒级阻塞; - 超时前被唤醒(如前驱节点释放锁)且成功获取,则返回
true; - 超时未获锁或被中断,则清理节点并返回
false或抛出InterruptedException; - 注意:这个版本已不是纯无开销操作,但相比无限等待的
lock(),仍可控且避免死等。
实际使用中的关键细节
写出高效安全的 tryLock() 代码,需注意:
- 必须配合 unlock() 使用:成功获取后务必在 finally 块中释放,否则导致死锁;
-
不能替代 synchronized 的语义:它不自动释放(无异常安全保证),也不支持隐式重入计数管理(需手动调用
getHoldCount()调试); - 适合场景明确:如轮询资源、避免长时间阻塞、实现乐观并发控制(如库存扣减失败立即重试或降级);
-
不要滥用在高竞争短临界区:若几乎每次都能抢到,
tryLock()比lock()略快;但若频繁失败再重试,CAS 自旋 + 再次调用开销可能反不如直接阻塞。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











