标准答案
- volatile 不适合保护需要读取、判断、更新的一组操作。
- synchronized 语义简单,进入和退出监视器时建立互斥和可见性。
- Lock 可使用 tryLock、lockInterruptibly、多个 Condition 等能力,但必须在 finally 中释放。
- 选择取决于共享不变式、临界区时长、取消要求和可维护性,不是关键字越复杂越好。
题目解析
volatile 适合发布状态和保证单变量可见性,synchronized 还提供互斥和内存同步,Lock 则提供可中断、超时、多个条件队列等控制。选择应从共享不变式和取消需求出发。
Lock 的灵活性意味着更多责任:获取成功后必须在 finally 释放,tryLock 超时和线程中断也要有明确的失败路径。复杂锁层次可能增加死锁和遗漏释放的概率。
如果只需要简单互斥,synchronized 往往更容易审查;如果只需单变量发布,volatile 更合适。性能优化必须建立在正确边界之上,并用竞争、等待和 P99 验证。
常见误区
- 误区:volatile 解决所有线程安全问题。改正:它不保护复合读改写,也不替代多个字段的一致更新。
- 误区:Lock 不需要 finally 释放。改正:lock 成功后必须在 finally 解锁,并处理取消和异常。
- 误区:为了性能把临界区拆到无法证明不变式。改正:先保留可证明的同步边界,再用 profile 评估细化。