LinkedBlockingQueue的fullyLock方法异常是否会引发锁泄露问题?
问题解答
1. 该场景是否有可能发生?
仅在JVM出现致命异常错误的极端场景下才有可能发生,常规业务运行过程中几乎不会出现。
2. 常规场景下不会发生的核心原因
首先明确ReentrantLock的lock()方法的特性:
lock()方法本身不响应线程中断,也不会抛出InterruptedException,执行到该方法时要么一直阻塞等待直到成功获取锁,要么拿到锁后继续向下执行,常规锁竞争场景下不会抛出任何异常- 只有当JVM出现栈溢出、OOM等非程序可控的
Error级错误,或是线程被调用已废弃的Thread.stop()强制终止时,才可能出现在putLock加锁成功后,takeLock加锁流程异常中断的情况
其次看remove()的实现逻辑,正常情况下只要fullyLock()执行完成,后续的逻辑都会走finally块调用fullyUnlock()同时释放两把锁,不会出现锁泄漏。
3. 极端场景下的补救方案
JDK层面优化
可以调整fullyLock的加锁逻辑,每成功获取一把锁就增加兜底释放逻辑,避免后续加锁失败导致已持有的锁泄漏:
void fullyLock() { putLock.lock(); boolean takeLockAcquired = false; try { takeLock.lock(); takeLockAcquired = true; } finally { if (!takeLockAcquired) { // 第二把锁加锁失败,释放已经持有的putLock putLock.unlock(); } } }
开发者层面注意事项
- 不要在代码中调用
Thread.stop()这类强制终止线程的废弃API,避免锁流程异常中断 - 自定义多锁逻辑时,要固定加锁顺序,同时加锁过程要增加兜底释放逻辑,避免锁泄漏
- 生产环境如果出现疑似锁泄漏的问题,可以通过
jstack等工具排查锁持有情况,临时重启服务恢复业务
内容的提问来源于stack exchange,提问作者jianjian
相关产品推荐
相关产品推荐

