volatile /synchronized/ Lock 如何保证 可见性、有序性、原子性
一、先记住 3 大特性是什么
- 可见性:一个线程改了变量,其他线程能立刻看到最新值
- 有序性:禁止 CPU 指令重排,代码按顺序执行
- 原子性:操作不可被打断,要么全部完成,要么不做
二、三者能力总表(直接背)
| 关键字 | 可见性 | 有序性 | 原子性 |
|---|---|---|---|
| volatile | ✅ 保证 | ✅ 保证 | ❌ 不保证 |
| synchronized | ✅ 保证 | ✅ 保证 | ✅ 保证 |
| Lock (ReentrantLock) | ✅ 保证 | ✅ 保证 | ✅ 保证 |
三、分别讲清楚:它们怎么保证的?
1. volatile 如何保证?
① 可见性
- 写 volatile 变量时,直接把工作内存刷新到主内存
- 读 volatile 变量时,直接从主内存重新读取
- 不使用副本,保证最新
② 有序性
- 加了 内存屏障(Memory Barrier)
- 禁止 CPU 指令重排
- 前面的代码不能跑到 volatile 后面,后面不能跑到前面
③ 为什么不保证原子性?
因为像
volatile 只能保证每一步可见,但不能保证三步不被打断
i++ 这种操作是 读 → 改 → 写 三步volatile 只能保证每一步可见,但不能保证三步不被打断
2. synchronized 如何保证?
① 可见性
- 解锁时,所有修改都会强制刷新回主内存
- 加锁时,会重新从主内存加载最新变量
② 有序性
- 加锁区域内的代码,具有 Happens-Before 规则
- 指令重排不会跨越锁区域
- 保证有序
③ 原子性
- 同一时刻只有一个线程能拿到锁
- 临界区代码完全独占,不可被中断
- 完美保证原子性
3. Lock(ReentrantLock)如何保证?
和 synchronized 原理几乎一样,但基于 AQS + volatile 实现
① 可见性
- lock () 时:从主内存读最新
- unlock () 时:强制刷新到主内存
② 有序性
- 内部使用 volatile 状态 + 内存屏障
- 禁止重排,保证有序
③ 原子性
- 同一时间只有一个线程能获取锁
- 临界区独占,保证原子性
四、最经典一句话总结(面试必背)
- volatile:可见性 + 有序性 ✅ ,原子性 ❌
- synchronized:可见性 + 有序性 + 原子性 全能 ✅
- Lock:和 synchronized 一样全能 ✅,更灵活
五、最简单记忆口诀
- volatile 管看不管改(可见、有序,不保证原子)
- synchronized 全能但重
- Lock 全能更灵活

浙公网安备 33010602011771号