ReentrantLock:解锁必须覆盖异常路径
持锁过程中业务抛异常,后续线程就一直等待,通常是因为 unlock 没有放进 finally。同步代码同样需要异常安全。
问题从哪里出现
持锁过程中业务抛异常,后续线程就一直等待,通常是因为 unlock 没有放进 finally。同步代码同样需要异常安全。
理解核心机制
lock 成功获得锁后,用 try/finally 包住受保护区域。tryLock 则先判断是否拿到锁,仅在成功时解锁。把持锁范围缩小,也能减少竞争和不必要的耦合。
动手做一个小实验
Java 17 或更新版本;将示例保存为 Demo.java,执行 javac Demo.java 后运行 java Demo。
import java.util.concurrent.locks.ReentrantLock;
public class Demo {
public static void main(String[] args) {
var lock = new ReentrantLock();
lock.lock();
try { System.out.println("protected operation"); }
finally { lock.unlock(); }
System.out.println(lock.isLocked());
}
}适用边界与常见误区
同一把锁只保护遵守同一协议的访问。不要在持锁时调用不可控的慢网络请求,也不要误以为公平锁总能提高吞吐。
继续练习
在受保护区域主动抛异常,再从另一个线程尝试获取锁;测试 finally 是否确实覆盖所有出口。