Java 指令重排

java 指令重排

package com.feshfans; /**
* 用来演示指令重排
* 指令重排会发生在两个阶段:
* 1. 编译期(jvm 加载字节码时)
* 2. cpu 执行期
* 但对于单线程来说,不管发生怎样的重排,都必须保持与源代码一致的输出结果(As-If-Serial).
* 上述规则保证了单线程的执行结果总是与预期一致,但在多线程的情况,就会出现与预期不一致的情况,
* 而导致这一情况发生的原因,正是指令重排
*
*/
public class InstructionReOrder { static Integer a = 0;
static Integer b = 0;
static Integer x = 0;
static Integer y = 0; private void showReOrder() throws InterruptedException { for(int i=0;i<Integer.MAX_VALUE;i++){
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
// 有可能发生重排,即 先执行 x = b,再执行 a = 1
a = 1;
x = b; }
}); Thread t2= new Thread(new Runnable() {
@Override
public void run() {
// 有可能发生重排,即先执行 y = a,再执行 b = 1;
b = 1;
y = a;
}
}); t1.start();
t2.start();
t1.join();
t2.join();
/**
* 如果没有指令重排,输出的可以结果为:(0,1)(1,1)(1,0)
* 但实际上有可能会输出(0,0)
*/
System.out.println("第 "+ i + "次,x="+x +", y="+y);
if(x == 0 && y == 0){
break;
}
a = b = 0;
x = y = 0;
}
} public static void main(String[] args) {
InstructionReOrder reOrder = new InstructionReOrder();
try {
reOrder.showReOrder();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

输出结果如下:


指令重排输出结果

从上图中可以看出,执行到第 65456 次时,发生了指令重排

Java 指令重排的更多相关文章

  1. 一篇讲Java指令重排和内存可见性的好文

    在这里: http://tech.meituan.com/java-memory-reordering.html 指令重排和内存可见性(缓存不一致)是两个不同的问题. volatile关键字太强,即阻 ...

  2. Java内存模型与指令重排

    Java内存模型与指令重排 本文暂不讲JMM(Java Memory Model)中的主存, 工作内存以及数据如何在其中流转等等, 这些本身还牵扯到硬件内存架构, 直接上手容易绕晕, 先从以下几个点探 ...

  3. Java并发编程(五)JVM指令重排

    我是不是学了一门假的java...... 引言:在Java中看似顺序的代码在JVM中,可能会出现编译器或者CPU对这些操作指令进行了重新排序:在特定情况下,指令重排将会给我们的程序带来不确定的结果.. ...

  4. Java并发:volatile内存可见性和指令重排

    volatile两大作用 1.保证内存可见性 2.防止指令重排 此外需注意volatile并不保证操作的原子性. (一)内存可见性 1 概念 JVM内存模型:主内存和线程独立的工作内存 Java内存模 ...

  5. Java中指令重排

    /** * 指令重排:代码执行顺序与预期不一致 (发生在前后行代码无联系时) * 目的:提高性能 * */ public class HappenBefore { private static int ...

  6. Java 多线程 -- 指令重排(HappenBefore)

    指令重排是指:代码执行顺序和预期不一致. 代码运行一般步骤为: 1.从内存中获取指令解码 2.计算值 3.执行代码操作 4.把结果写回内存 而写回内存的操作比较耗时,CPU为了性能,可能不会等它完成, ...

  7. JVM内存模型、指令重排、内存屏障概念解析

    在高并发模型中,无是面对物理机SMP系统模型,还是面对像JVM的虚拟机多线程并发内存模型,指令重排(编译器.运行时)和内存屏障都是非常重要的概念,因此,搞清楚这些概念和原理很重要.否则,你很难搞清楚哪 ...

  8. happens-before规则和指令重排

                                                                                                         ...

  9. JVM内存模型、指令重排、内存屏障概念解析(转载)

    在高并发模型中,无是面对物理机SMP系统模型,还是面对像JVM的虚拟机多线程并发内存模型,指令重排(编译器.运行时)和内存屏障都是非常重要的概念,因此,搞清楚这些概念和原理很重要.否则,你很难搞清楚哪 ...

随机推荐

  1. Responsive web design 学习笔记

    Advanced Styling with Responsive Design 此笔记为Coursera同名课程笔记. Week1 什么是响应式设计? 响应式设计: It is designing y ...

  2. Redis 常用命令 大全

    Redis 常用命令 发现几个很好的 Redis 常用命令汇总大全网页,分享给小伙伴们~ 1.Redis 命令参考 http://redisdoc.com/string/index.html 2.W3 ...

  3. java:Mybatis框架2(基于mapper接口的开发,多种查询,复合类型查询,resultMap定义,多表联查,sql片段)

    1.mybatis02: mybatis-config.xml: <?xml version="1.0" encoding="UTF-8"?> &l ...

  4. java:LeakFilling(struts2)

    1.mvc: 目的: 将展现和业务相分离. Model1:JSP+JavaBean Model2:MVC(JSP+Servlet+JavaBean) 优点: A.各司其职,互不干涉 B.有利于分工协作 ...

  5. Shell编程、part4

    本节内容 1. shell函数 2. shell正则表达式 shell函数 shell中允许将一组命令集合或语句形成一段可用代码,这些代码块称为shell函数.给这段代码起个名字称为函数名,后续可以直 ...

  6. Java基础/Java异常

    Java异常 1.异常的分类: ① 非运行时异常(Checked Exception) Java中凡是继承自Exception但不是继承自RuntimeException的类都是非运行时异常 ② 运行 ...

  7. git diff 命令用法

    理解git diff的前提,首先要理解git中工作区,暂存区,本地版本库的概念,如果头脑中有这些概念,接着往下读. git diff test.c 用来查看工作区和暂存区中test.c文件的区别. g ...

  8. MySQL 分组统计查询 表连接(3)

    1 查询底薪超过公司平均底薪的员工信息? select e.empno,e.ename,e.salfrom t_emp as e join (select avg(sal) as avg from t ...

  9. java_时间戳与Date_相互转化的实现代码

    转载自: java_时间戳与Date_相互转化的实现代码

  10. Nginx + Tomcat动静分离 (转)

    什么是动静分离 为了提高网站的响应速度,减轻程序服务器(Tomcat,Jboss等)的负载,对于静态资源比如图片,js,css等文件,我们可以在反向代理服务器中进行缓存,这样浏览器在请求一个静态资源时 ...