acquire() 必须处理 InterruptedException,因中断是协作指令而非错误;应响应中断(清理资源后退出)或恢复中断状态后抛出;需确保 acquire 成功才执行临界区,且 release 必须在 finally 中配对。

直接用 acquire() 就必须处理 InterruptedException,这不是编译器“找茬”,而是 Java 并发设计的明确契约:它在告诉你——这个操作是可中断的,你得对线程协作负责。
必须捕获并表态,不能“生吞”
空 catch 块(catch (InterruptedException e) {})或只打印日志,等于抹掉中断信号。线程后续可能卡死、无法响应关闭指令、资源泄漏风险陡增。
- 中断不是错误,是协作指令;忽略它会让上层失去取消能力
- 不要用
e.printStackTrace()代替处理逻辑 - 即使当前方法不打算退出,也必须显式表态——恢复中断状态或立即响应
两种合规路径选其一
根据方法角色决定怎么处理:
- 若该方法本身是业务主流程(如
Runnable.run()、任务执行体),推荐响应中断:清理资源(如关闭流、释放锁)、退出循环或直接 return - 若该方法是工具类或库方法(如封装了 acquire 的辅助方法),推荐恢复中断并向上抛出:调用
Thread.currentThread().interrupt()后,再throw e或声明throws InterruptedException
别踩 acquire() 的典型陷阱
acquire() 被中断时不会获得许可,这是关键前提。很多 bug 源于误以为“进了 catch 就等于拿到了许可”。
- 务必确保
acquire()成功后才执行临界区逻辑;异常分支里不能继续用资源 - 每次
acquire()必须严格配对release(),且 release 应放在 finally 块中 - 需要限时等待?改用
tryAcquire(long, TimeUnit),它返回 boolean,不抛中断异常(但超时中被中断仍会抛)
替代方案:按场景换更安全的调用
不是所有地方都非用 acquire() 不可:
- 用户请求、API 接口等对延迟敏感的场景,优先用
tryAcquire(timeout, unit)避免无限阻塞 - 若业务逻辑不允许中断(比如必须完成某段原子操作),可用
acquireUninterruptibly(),但它会丢失中断信号——仅限你明确接受该代价 - 注意:
acquireUninterruptibly()不是“更简单”的选择,而是“放弃协作权”的妥协

















