面试官在问到多线程编程的时候,指令重排序、内存屏障经常会被提起。如果你对这两者有一定的理解,那这就是你的加分项。

(一)什么是指令重排序

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

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

在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=aThread thread1=new Thread(new Runnable() {@Overridepublic void run() {//线程1会比线程2先执行,因此用nanoTime让线程1等待线程2 0.01毫秒shortWait(10000);a=1;x=b;}});Thread thread2=new Thread(new Runnable() {@Overridepublic 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=b;并且我把 a 和 b 修饰为 volatile。

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

执行 x=b 时,它相当于先执行 volatile 读取 b,再执行普通写 x 等于 b;

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

第一个操作是 volatile 写操作,第二个操作是 volatile 读操作,那么表格中对应的值就是 NO,禁止重排序。这就是 Volatile 进行指令重排序的原理。

现在,只需要把上面代码的 a 和 b 用 volatile 修饰,就不会发生指令重排序了。

什么是指令重排序和内存屏障,看完你就懂了相关推荐

  1. Java指令屏障_指令重排序和内存屏障

    sap hana计算技术项目实战指南内存 61元 (需用券) 去购买 > 一.指令重排序 指令重排序分为三种,分别为编译器优化重排序.指令级并行重排序.内存系统重排序.如图所示,后面两种为处理器 ...

  2. java volidate线程安全_03.(多线程与并发)面试题-02--Volidate的原理和指令重排序

    线程栈(线程的工作内存)保存了线程运行时候变量值信息.当线程访问某一个对象时候值的时候,首先通过对象的引用找到对应在堆内存的变量的值,然后把堆内存变量的具体值load到线程本地内存中,建立一个变量副本 ...

  3. JVM学习--(二)内存模型、可见性、指令重排序

    我们将根据JVM的内存模型探索java当中变量的可见性以及不同的java指令在并发时可能发生的指令重排序的情况. 内存模型 首先我们思考一下一个java线程要向另外一个线程进行通信,应该怎么做,我们再 ...

  4. 说说Java中原子性,可见性与指令重排序的理解

    原子性:就是读数据,处理数据,写数据 这三个步骤不能被终止,或者打断:就是不能被线程调度器中断,切换线程. 这样,才能保证,原子操作在线程切换,并行处理上保证数据地顺序累加处理. 可见性:是Jvm较为 ...

  5. Java之volatile如何保证可见性和指令重排序

    1 我们先了解CPU缓存 CPU缓存为了解决CPU运算速度与内存读写速度不匹配的问题,因为CPU运算速度要比内存读写速度快得多 一次主内存的访问通常在几十到几百个时钟周期 一次L1高速缓存的读写只需要 ...

  6. java重排序_Java synchronized 能防止指令重排序吗?

    @ZealTalk 说的是 synchronized 可以防止指令重排,这个观点不对的,也欢迎回答的各位来讨论 synchronized 的有序性 来讨论这个问题先,先看看 Java 里的操作无序现象 ...

  7. 由Java引起的指令重排序思考

    背景 问题出现 最近遇到了一个NullPointerException,虽然量不大,但是很怪异,大致长这个样子 这是个什么空指针?居然说我LinkedList.iterator().hasNext() ...

  8. Java并发编程之指令重排序

    在我们面试过程中,通常避免不了会被问到什么是指令重排序?本文就这个问题进行探索. 重排序 前言 一.重排序种类 二.happens-before 三.重排序 1.数据依赖性 2. as-if-seri ...

  9. CPU流水线与指令重排序

    目录 1. Compiler Reordering 2. CPU 流水线 2.1. 从汽车装配谈起 2.2. 现代CPU的流水线 3. 超长流水线的瓶颈 3.1. 性能瓶颈 3.2. 功耗瓶颈 3.3 ...

最新文章

  1. 《R语言实战》读书笔记--第一章 R语言介绍
  2. 收藏 | 卷积神经网络中十大拍案叫绝的操作
  3. java 操作vss,java开发常用工具总结,java开发常用工具
  4. 一套代码小程序WebNative运行的探索03——处理模板及属性
  5. HDU 1210 Eddy's 洗牌问题(foj1062) || FOJ1050 Number lengths水
  6. electron 自定义标题栏_electron+vue制作桌面应用--自定义标题栏
  7. Winform开发技术详解 - 应用环境 相关技术介绍
  8. 如何学习SAP系统并从事相关职业
  9. 硬盘:主分区、扩展分区、逻辑分区、活动分区、系统分区、启动分区、引导扇区、MBR解析
  10. Source Insight 4.0 选中高亮
  11. 打印机 针式打印机 热敏打印机
  12. 内存泄漏、虚拟内存、物理内存的联系
  13. 20种简单美化照片PS技术
  14. 重置CISCO 2911SEC/K9路由器密码
  15. tp5微信开发(二) ---- 微信关键字自动回复,图文回复,关注自动回复
  16. 爬虫小白入门实例 —— 爬取全国某天所有火车的运行时刻表
  17. “防不胜防”的智能助理:Alexa秒变诈骗工具
  18. 最小二乘拟合n阶多项式【Matlab】
  19. 梳状谱干扰matlab仿真,干扰信号MATLAB仿真.ppt
  20. 怎么在Word中制作表格?简单的Word表格制作方法分享

热门文章

  1. 中南大学计算机学院夏令营2018,中南大学信息院的夏令营
  2. 【Flask框架】——Flask介绍
  3. 福克斯2011时尚型1.8AT 自己保养记录
  4. 程序员 = 态度 ? 码农 : 码奴;
  5. 计算机毕业设计Python+uniapp今日健康饮食食谱小程序(小程序+源码+LW)
  6. 华为前高管:华为为什么不上市
  7. 手机隐藏的实用技巧,很少有人会使用
  8. 华为防火墙的负载均衡
  9. 复旦大学+计算机学院张巍,“相勉课堂”第二期圆满结业
  10. 星载激光雷达的数据读取与显示