千家信息网

如何实现指令重排序

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,本篇内容主要讲解"如何实现指令重排序",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"如何实现指令重排序"吧!(一)什么是指令重排序为了使处理器内部的运算单元
千家信息网最后更新 2026年11月03日如何实现指令重排序

本篇内容主要讲解"如何实现指令重排序",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"如何实现指令重排序"吧!

(一)什么是指令重排序

为了使处理器内部的运算单元能尽量被充分利用,处理器可能会对输入的代码进行乱序执行优化,处理器会在计算之后将乱序执行的结果重组,并确保这一结果和顺序执行结果是一致的,但是这个过程并不保证各个语句计算的先后顺序和输入代码中的顺序一致。这就是指令重排序。

简单来说,就是指你在程序中写的代码,在执行时并不一定按照写的顺序。

在Java中,JVM能够根据处理器特性(CPU多级缓存系统、多核处理器等)适当对机器指令进行重排序,最大限度发挥机器性能。

Java中的指令重排序有两次,第一次发生在将字节码编译成机器码的阶段,第二次发生在CPU执行的时候,也会适当对指令进行重排。

(二)复现指令重排序

光靠说不容易看出现象,下面来看一段代码,这段代码网上出现好多次了,但确实很能复现出指令重排序。我把解释放在代码后面。

public class VolatileReOrderSample {    //定义四个静态变量    private static int x=0,y=0;    private static int a=0,b=0;    public static void main(String[] args) throws InterruptedException {        int i=0;        while (true){            i++;            x=0;y=0;a=0;b=0;            //开两个线程,第一个线程执行a=1;x=b;第二个线程执行b=1;y=a            Thread thread1=new Thread(new Runnable() {                @Override                public void run() {                    //线程1会比线程2先执行,因此用nanoTime让线程1等待线程2 0.01毫秒                    shortWait(10000);                    a=1;                    x=b;                }            });            Thread thread2=new Thread(new Runnable() {                @Override                public void run() {                    b=1;                    y=a;                }            });            thread1.start();            thread2.start();            thread1.join();            thread2.join();            //等两个线程都执行完毕后拼接结果            String result="第"+i+"次执行x="+x+"y="+y;            //如果x=0且y=0,则跳出循环            if (x==0&&y==0){                System.out.println(result);                break;            }else{                System.out.println(result);            }        }    }    //等待interval纳秒    private static void shortWait(long interval) {        long start=System.nanoTime();        long end;        do {            end=System.nanoTime();        }while (start+interval>=end);    }}

这段代码虽然看着长,其实很简单,定义四个静态变量x,y,a,b,每次循环时让他们都等于0,接着用两个线程,第一个线程执行a=1;x=b;第二个线程执行b=1;y=a。

这段程序有几个结果呢?从逻辑上来讲,应该有3个结果:

当第一个线程执行到a=1的时候,第二个线程执行到了b=1,最后x=1,y=1;

当第一个线程执行完,第二个线程才刚开始,最后x=0,y=1;

当第二个线程执行完,第一个线程才开始,最后x=1,y=0;

理论上无论怎么样都不可能x=0,y=0;

但是当程序执行到几万次之后,竟然出现了00的结果:

这就是因为指令被重排序了,x=b先于a=1执行,y=a先于b=1执行。

(三)通过什么方式禁止指令重排序?

Volatile通过内存屏障可以禁止指令重排序,内存屏障是一个CPU的指令,它可以保证特定操作的执行顺序。

内存屏障分为四种:

StoreStore屏障、StoreLoad屏障、LoadLoad屏障、LoadStore屏障。

JMM针对编译器制定了Volatile重排序的规则:

光看这些理论可能不容易懂,下面我就用通俗的话语来解释一下:

首先是对四种内存屏障的理解,Store相当于是写屏障,Load相当于是读屏障。

比如有两行代码,a=1;x=2;并且我把x修饰为volatile。

执行a=1时,它相当于执行了一次普通的写操作;

执行x=2时,它相当于执行了一次volatile的写操作;

因此在这两行命令之间,就会插入一个StoreStore屏障(前面是写后面也是写),这就是内存屏障。

再让我们看表,如果第一个操作是普通写,第二个操作是volatile写,那么表格中对应的值就是NO,禁止重排序。这就是Volatile进行指令重排序的原理。

现在,我们只需要把上面代码的x和y用volatile修饰,就不会发生指令重排序了(如果你能通过表推一遍逻辑,你就能懂了)。

到此,相信大家对"如何实现指令重排序"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

线程 指令 屏障 代码 结果 就是 内存 处理器 顺序 处理 两个 机器 程序 普通 适当 一致 内容 变量 时候 理论 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技巨头监管 互联网巨头科技公司 互联网科技开发公司 互联网科技集团 互联网女皇 腾讯科技 互联网科技小额贷款 人人互联网科技是培训 科技大学互联网专业好不好 互联网汽车科技小镇 玖二柒互联网科技公司待遇 常德市电业局互联网科技部 华服互联网科技官网 重庆互联网医院沙龙医盟信息科技 智帮互联网科技公司最近动向 互联网科技快讯热点 萌小萌互联网科技河南有限公司 科技互联网公司两年变化 华人运通互联网科技公司 互联网领先科技成果宣传视频 科技互联网企业在行动 中国互联网科技工作委员会毛军 网络科技有限互联网 互联网高科技股票 济南华为互联网科技产业总部基地 厦门比较好的科技互联网公司 互联网金融科技公司的优势 启辰互联网科技 互联网时代高科技布局 重庆科技产业互联网有哪些 山东亿川互联网科技有限责任公司
0