reentrantlock 是显式锁,需手动加锁解锁且支持公平锁、trylock、条件队列等高级特性;synchronized 是隐式锁,jvm 自动管理,更简洁安全。
ReentrantLock 和 synchronized 有什么关键区别
ReentrantLock 是显式锁,必须手动 lock() 和 unlock();而 synchronized 是隐式锁,JVM 自动加锁/释放。这意味着一旦忘记 unlock(),就会永久阻塞其他线程——这是最常踩的坑。
它支持公平锁(new ReentrantLock(true))和非公平锁(默认),还提供 tryLock()、lockInterruptibly()、条件队列(newCondition())等能力,synchronized 没有这些。
性能上,高竞争场景下 ReentrantLock 可能更优(尤其配合自旋或超时重试),但日常低竞争代码中差异几乎不可测,别为“看起来更高级”而强行替换 synchronized。
必须用 try-finally 包裹 unlock() 吗
是的,必须。哪怕只有一行临界区代码,也得确保 unlock() 在异常路径下仍执行。Java 7+ 的 try-with-resources 不适用,因为 ReentrantLock 没实现 AutoCloseable。
立即学习“Java免费学习笔记(深入)”;
- 错误写法:
lock.lock(); doSomething(); lock.unlock();—— 若doSomething()抛异常,unlock()永远不执行 - 正确写法:
lock.lock(); try { doSomething(); } finally { lock.unlock(); } - 注意:不能把
lock()放进try块里——如果加锁失败(如被中断),finally会尝试对未持有锁的对象调用unlock(),抛IllegalMonitorStateException
什么时候该用 tryLock() 而不是 lock()
tryLock() 是非阻塞加锁,立即返回 true(成功)或 false(失败),适合避免死锁、实现限时等待、或构建“尽力而为”的并发逻辑。
典型场景包括: