关于 CPU 乱序执行的证明
在学习 volatile 关键字的时候,我们都知道他有两个作用:1. 内存可见性;2. 禁止指令重排序。但是我们一般都是说,那么怎么证明呢?请看下面这段代码:
package cn.bridgeli.demo; /** * @author BridgeLi * @date 2020/7/4 10:27 */ public class Disorder { private static int x = 0; private static int y = 0; private static volatile int a = 0; private static volatile int b = 0; public static void main(String[] args) throws InterruptedException { int i = 0; for (; ; ) { i++; x = 0; y = 0; a = 0; b = 0; Thread one = new Thread(new Runnable() { @Override public void run() { a = 1; x = b; } }, "one"); Thread two = new Thread(new Runnable() { @Override public void run() { b = 1; y = a; } }, "two"); one.start(); two.start(); one.join(); two.join(); if (0 == x && 0 == y) { System.out.println("第 " + i + " 次(" + x + ", " + y + ")"); break; } } } }
如果仔细分析这段代码,我们就会发现,如果 CPU 没有乱序执行,那么无论任何时候 x 和 y 都不可能同时为零,但是事实上,这段代码是有可能出现 x 和 y 同时为零的,具体大家可以自己测试,需要说明的时候,什么时候指令重排了,要看运气,可能很快出现,也可能要等一会。
不过需要说明的是,实际上 CPU 的乱序执行,说的是指令级别的乱序执行,也就是:
Object o = new Object();
编译成字节码会有多条指令,例如实例化、初始化、o 指向申请的内存空间等等,而初始化和 o 指向申请的内存空间是可以乱序执行的,所以这也是 DCL 单例锁要加 volatile 关键字的原因。
最后简单说一下 volatile 是如何做的禁止指令重排
Java 内存模型其实是通过内存屏障(Memory Barrier)来实现的,Java 内存模型的重排规则会要求 Java 编译器在生成 JVM 指令时插入特定的内存屏障指令,通过这些内存屏障指令来禁止特定的指令重排序。在 hotspot 中的实现,在 bytecodeinterpreter.cpp 源码中有这么一段代码:
int field_offset = cache->f2_as_index(); if (cache->is_volatile()) { if (support_IRIW_for_not_multiple_copy_atomic_cpu) { OrderAccess::fence(); }
具体到 orderaccess_linux_x86.inline.hpp 源码中:
inline void OrderAccess::fence() { if (os::is_MP()) { // always use locked addl since mfence is sometimes expensive #ifdef AMD64 __asm__ volatile ("lock; addl $0,0(%%rsp)" : : : "cc", "memory"); #else __asm__ volatile ("lock; addl $0,0(%%esp)" : : : "cc", "memory"); #endif } }
也就是通过 lock addl 指令锁北桥总线,实现禁止指令重排
参考资料:马士兵教育,多线程与高并发
全文完,如果本文对您有所帮助,请花 1 秒钟帮忙点击一下广告,谢谢。
作 者: BridgeLi,https://www.bridgeli.cn
原文链接:http://www.bridgeli.cn/archives/682
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。
作 者: BridgeLi,https://www.bridgeli.cn
原文链接:http://www.bridgeli.cn/archives/682
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。
近期评论