volatile 可以 禁止 JVM 的 " 指令重排 " ; 保证 有序性 ; 一、指令重排序规范 指令重排指的是 , 线程中如果两行代码 没有逻辑上的上下关系 , 可以对代码进行 重新排序 ; JVM 指令重排遵循规范 : as-if-serial 规范 :单个线程中, 指令的重排 , 不能影响程序的执行结果 ; 可以重排的情况 :对于下面代...
这种指令重排是JIT编译之后的结果。处理器的乱序执行是当前指令在Load数据等待中,cpu可能先执行下面的指令了。 为什么JIT会进行重排序呢?我们知道我们java文件编译成class文件,然后JVM编译成指令序列再到汇编指令,JVM有两个编译方式,一种是读取一行解释一行,这种效率自然是很慢的,还有一种是JIT即时编译它会检测一些频繁...
int b=2; 我们要系统禁止这2行代码进行重排,我们需要定义一个规范,就像产品经理说,我要实现某个功能,这是一种规范,真正实现由程序员去弄,现在假设我们的规范是,只要这两行代码中有abc三个字母就禁止重排 int a=1; abc; int b=2; 然后我们系统发现有abc就不会重排了,具体实现这个需求,是由jvm厂商去实现,...
发生了指令重排,才会出现 x = 0 并且 y = 0 的情况。 若不发生指令重排,不可能出现 x = 0 并且 y = 0 的情况。 二、Volatile 是如何禁止指令重排的? 实现过程 Java代码层面:Volatile 关键字 Java字节码层面:ACC_VOLATITLE JVM内存屏障:屏障两边的指令不可以重排序,保障有序! hotspot 实现: bytecodeinterp...
而如果我们使用volatile关键字修饰instance变量,这种情况就可以避免,因为被volatile修饰的变量不会被jvm进行指令重排序,所以也就不会出现先执行3,后执行2的情况发生。所以instance只要是非空,就一定是已经初始化完毕的。 回到题目问的问题:那么volatile为什么能禁止指令重排呢?
(2)顺序性的保证:禁止JVM或者CPU对进行指令重排。 可见性保证举例: //线程A boolean running= true; public void run(){ while(running){ System.out.println(“hello!”); } } //线程B public void setRunStatus(boolean running){ this. running = running; ...
所以 JVM 是可以针对它们进行指令的优化重排序的,经过重排序后如下: memory =allocate(); //1:分配对象的内存空间 instance =memory; //3:instance指向刚分配的内存地址,此时对象还未初始化 ctorInstance(memory); //2:初始化对象 指令重排之后,instance 指向分配好的内存放在了前面,而这段内存的初始化被排在...
volatile 可以 禁止 JVM 的 " 指令重排 " ; 保证 有序性 ; 一、指令重排序规范 指令重排指的是 , 线程中如果两行代码 没有逻辑上的上下关系 , 可以对代码进行 重新排序 ; JVM 指令重排遵循规范 : as-if-serial 规范 : 单个线程中, 指令的重排 , ...
在底层实现上,volatile 的原理依赖于处理器提供的内存屏障(Memory Barrier)。内存屏障是一种 CPU 指令,它的作用是防止指定的内存操作被重排列。当一个变量被声明为 volatile 时,JVM 会在生成的字节码中插入内存屏障指令,以确保对这个变量的读写操作符合 volatile 的语义。
这是因为volatile关键字禁止了指令重排序优化。具体来说,当写入一个volatile变量时,JVM会清空CPU的指令缓存,使得写入操作立即生效,并被其他线程立即感知。同样地,当读取一个volatile变量时,JVM也会清空CPU的指令缓存,确保读操作能够获取到最新的值。 2.2 有序性...