关于 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
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。
近期评论