1. 核心区别概述
| 特性 | volatile | synchronized |
|---|---|---|
| 作用范围 | 仅修饰变量 | 修饰代码块或方法 |
| 原子性 | 仅保证单次读/写原子性(如 long/double) | 保证代码块/方法的原子性 |
| 可见性 | 强制线程从主内存读取最新值 | 保证进入同步块前刷新变量,退出后写回 |
| 有序性 | 禁止指令重排序 | 保证同步块内有序执行 |
| 阻塞性 | 非阻塞(仅内存屏障) | 阻塞(线程竞争锁会挂起) |
| 适用场景 | 状态标志、一次性发布(如 DCL) | 复合操作(如 i++)、临界区保护 |
| 锁机制 | 无锁,仅内存屏障 | 基于 Monitor 锁(JVM 实现) |
| 性能 | 读操作接近普通变量,写稍慢 | 较高开销(涉及线程阻塞/唤醒) |
2. 详细对比
(1) 原子性
-
volatile-
仅保证单次读/写操作的原子性(如
volatile int x = 10是原子的)。 -
不保证复合操作的原子性(如
x++不是原子的,因为它包含read-modify-write三步)。
-
-
synchronized-
保证整个同步块的原子性(如
synchronized { x++; }是原子的)。
-
示例:
// volatile 不能保证原子性
volatile int count = 0;
count++; // 非原子操作(实际是 read + modify + write)
// synchronized 保证原子性
synchronized (this) {
count++; // 原子操作
}
(2) 可见性
-
volatile-
强制所有线程从主内存读取最新值,修改后立即写回主内存。
-
适用于状态标志(如
volatile boolean flag)。
-
-
synchronized-
进入同步块前,强制刷新工作内存(读取最新值)。
-
退出同步块时,强制写回主内存。
-
示例:
// volatile 保证可见性
volatile boolean running = true;
// synchronized 保证可见性
synchronized (lock) {
if (condition) {
// ...
}
}
(3) 有序性(防止指令重排序)
-
volatile-
通过内存屏障禁止 JVM 和 CPU 对指令重排序。
-
典型应用:DCL(双重检查锁)单例模式。
-
-
synchronized-
同步块内的代码顺序执行,不会重排序。
-
示例(DCL 单例模式):
class Singleton {
private static volatile Singleton instance; // 防止指令重排
public static Singleton getInstance() {
if (instance == null) { // 第一次检查(无锁优化)
synchronized (Singleton.class) {
if (instance == null) { // 第二次检查(防止多线程多次创建)
instance = new Singleton(); // volatile 防止重排序
}
}
}
return instance;
}
}
(4) 阻塞性
-
volatile-
非阻塞,仅通过内存屏障保证可见性和有序性。
-
适合轻量级同步(如状态标志)。
-
-
synchronized-
阻塞,未获取锁的线程会进入
BLOCKED状态。 -
适合临界区保护(如计数器、共享资源访问)。
-
3. 如何选择?
| 场景 | 推荐方案 | 原因 |
|---|---|---|
单变量状态标志(如 boolean) | volatile | 轻量级,无锁,性能高 |
复合操作(如 i++) | synchronized | 保证原子性 |
| DCL 单例模式 | volatile + synchronized | 防止指令重排 + 原子性 |
| 复杂同步逻辑 | synchronized 或 ReentrantLock | 更灵活的控制 |
4. 总结
-
volatile适用于单变量可见性和防止指令重排(如 DCL 单例)。 -
synchronized适用于复合操作和临界区保护(如计数器、共享资源)。 -
volatile不能替代synchronized,它仅适用于特定场景。
回答示例:
"
volatile和synchronized都能保证可见性,但synchronized还能保证原子性和互斥访问。volatile适用于状态标志等简单场景,而synchronized适用于需要原子操作的场景。例如,i++必须用synchronized,而boolean标志可以用volatile优化性能。"

被折叠的 条评论
为什么被折叠?



