volatile 是 Java 中用于保证可见性和禁止指令重排序的关键字,但不保证原子性。下面从原理层面解释为什么会这样。
当一个线程修改了 volatile 变量,其他线程立即可见。
原理:
volatile 变量会:
volatile 变量会:
✅ 解决的是:一个线程改了,别的线程能看到
volatile 前的操作,不会被重排到写之后volatile 后的操作,不会被重排到读之前✅ 解决的是:多线程下的执行顺序问题
i++volatile int i = 0;
i++;
表面上是一行代码,实际是三步操作:
i(从主内存)i + 1i假设 i = 0:
| 时间 | 线程 A | 线程 B |
|---|---|---|
| T1 | 读 i = 0 | |
| T2 | 读 i = 0 | |
| T3 | 计算 0+1 | 计算 0+1 |
| T4 | 写 i = 1 | 写 i = 1 |
最终结果:i = 1(而不是 2)
❌ 虽然每次写都可见,但读—改—写不是原子的
volatile boolean flag = true;
flag = false; // 原子
i++i += ncheck-then-act(先判断再修改)synchronizedsynchronized (this) {
i++;
}
AtomicInteger i = new AtomicInteger(0);
i.incrementAndGet();
底层使用 CAS(Compare And Swap),无锁且高效。
volatile 解决“看得见”,不解决“一起做”
如果你愿意,我也可以从 JMM(Java 内存模型) 或 CPU 缓存一致性协议(MESI) 的角度再深入讲一层。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。