Java synchronized 与 volatile
synchronized 提供互斥与可见性,volatile 提供可见性与有限有序性:何时用锁、何时用 volatile。
#type / concept
#status / growing
#tech / dev
#resource / java
[!info] 关联笔记
Java synchronized 与 volatile
这个概念为什么出现
多线程共享可变状态时,不仅会“算错”,还会因缓存/重排序导致看见过期值。synchronized 提供临界区互斥与内存语义;volatile 让单次读写具备可见性与特定有序性,但不提供复合操作原子性。
[!abstract] 一句话理解
synchronized保证同一锁上互斥并建立 happens-before;volatile保证可见性与部分有序,不适合count++这类读改写。
最小可运行示例
场景:库存扣减必须互斥;开关标志用 volatile 发布
public class InventoryGuard {
private int stock;
private volatile boolean open = true; // 状态发布
InventoryGuard(int stock) { this.stock = stock; }
synchronized boolean reserve(int qty) {
if (!open) return false;
if (stock < qty) return false;
stock -= qty; // 读改写需要互斥
return true;
}
void close() { open = true; } // 示例:可见性发布(业务可设 false)
void shutdown() { open = false; }
synchronized int stock() { return stock; }
public static void main(String[] args) throws Exception {
InventoryGuard g = new InventoryGuard(1);
Thread t1 = new Thread(() -> System.out.println("t1=" + g.reserve(1)));
Thread t2 = new Thread(() -> System.out.println("t2=" + g.reserve(1)));
t1.start(); t2.start();
t1.join(); t2.join();
System.out.println("left=" + g.stock());
}
}
建议运行:
javac InventoryGuard.java && java InventoryGuard
期望输出(顺序可互换,但成功预留恰好一次):
t1=true
t2=false
left=0
或 t1/t2 对调。
结合场景再看三个关注点
stock -= qty必须在同一把锁内。volatile适合旗标/发布,不适合复合更新。- 锁粒度影响性能与死锁风险。
核心概念与准确模型
1. synchronized
- 实例方法锁
this - static 方法锁
Class对象 - 同步块可指定锁对象
2. volatile
- 读看到最新写(在 JMM 规则下)
- 不保证
i++原子 - 适合独立状态旗标、安全发布某些引用
3. 与 JMM
完整 happens-before 规则见 内存模型。
边界情况与反直觉行为
- 同步库不一致(有的路径加锁有的不加)= 等于没锁。
- 锁顺序相反 → 死锁。
- 在锁内做远程 IO → 吞吐崩坏。
常见误区
[!warning] 常见误区:变量加了 volatile 就线程安全 复合操作仍需锁或原子类。
工程实践
- 优先高阶并发工具/不可变/分区。
- 锁内逻辑尽量短。
- 私有 final 锁对象避免外部抢锁。
- 用测试与 jctools/并发测试思路验证(至少多线程复现)。
本节总结
- 互斥用锁;可见性旗标可用 volatile
- 读改写不是 volatile 的工作
- 为 JUC 与 JMM 深化做准备
自测题
- 为什么
volatile int c; c++不安全? - synchronized 方法与同步块差别?
参考答案
- c++ 是读-改-写三步,可交错。
- 方法锁固定为 this/Class;同步块可更细粒度选锁与范围。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| Synchronization (Tutorial) | 教程 | synchronized |
| JLS volatile | 规范 | volatile 语义 |