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 指令重排的更多相关文章
- 一篇讲Java指令重排和内存可见性的好文
在这里: http://tech.meituan.com/java-memory-reordering.html 指令重排和内存可见性(缓存不一致)是两个不同的问题. volatile关键字太强,即阻 ...
- Java内存模型与指令重排
Java内存模型与指令重排 本文暂不讲JMM(Java Memory Model)中的主存, 工作内存以及数据如何在其中流转等等, 这些本身还牵扯到硬件内存架构, 直接上手容易绕晕, 先从以下几个点探 ...
- Java并发编程(五)JVM指令重排
我是不是学了一门假的java...... 引言:在Java中看似顺序的代码在JVM中,可能会出现编译器或者CPU对这些操作指令进行了重新排序:在特定情况下,指令重排将会给我们的程序带来不确定的结果.. ...
- Java并发:volatile内存可见性和指令重排
volatile两大作用 1.保证内存可见性 2.防止指令重排 此外需注意volatile并不保证操作的原子性. (一)内存可见性 1 概念 JVM内存模型:主内存和线程独立的工作内存 Java内存模 ...
- Java中指令重排
/** * 指令重排:代码执行顺序与预期不一致 (发生在前后行代码无联系时) * 目的:提高性能 * */ public class HappenBefore { private static int ...
- Java 多线程 -- 指令重排(HappenBefore)
指令重排是指:代码执行顺序和预期不一致. 代码运行一般步骤为: 1.从内存中获取指令解码 2.计算值 3.执行代码操作 4.把结果写回内存 而写回内存的操作比较耗时,CPU为了性能,可能不会等它完成, ...
- JVM内存模型、指令重排、内存屏障概念解析
在高并发模型中,无是面对物理机SMP系统模型,还是面对像JVM的虚拟机多线程并发内存模型,指令重排(编译器.运行时)和内存屏障都是非常重要的概念,因此,搞清楚这些概念和原理很重要.否则,你很难搞清楚哪 ...
- happens-before规则和指令重排
...
- JVM内存模型、指令重排、内存屏障概念解析(转载)
在高并发模型中,无是面对物理机SMP系统模型,还是面对像JVM的虚拟机多线程并发内存模型,指令重排(编译器.运行时)和内存屏障都是非常重要的概念,因此,搞清楚这些概念和原理很重要.否则,你很难搞清楚哪 ...
随机推荐
- Linux监控命令之==>lsof
一.命令说明 lsof 命令的原始功能是列出打开的文件的进程,但LINUX 下,所有的设备都是以文件的行式存在的,所以,lsof 的功能很强大. 二.参数说明 -a :列出打开文件存在的进程 -c&l ...
- Python的22个编程技巧,请收下!
1. 原地交换两个数字 Python 提供了一个直观的在一行代码中赋值与交换(变量值)的方法,请参见下面的示例: x,y= 10,20 print(x,y) x,y= y,x print(x,y) # ...
- Service Mesh体验
前言# 计算机软件技术发展到现在,软件架构的演进无不朝着让开发者能够更加轻松快捷地构建大型复杂应用的方向发展.容器技术最初是为了解决运行环境的不一致问题而产生的,随着不断地发展,围绕容器技术衍生出来越 ...
- python文档的数据读取,把读取数据写入到新的表里
目的:接口自动化过程需要从表格文件读取,然后把结果写到表格中.没有多余内容全部是精华! 读取文件1 读取文件2 代码如下图: # -*-coding:utf-8 -*-# Author:wangjun ...
- Spring Boot 2.0 多数据源编程
多数据源配置 创建一个Spring配置类,定义两个DataSource用来读取application.properties中的不同配置.如下例子中,主数据源配置为spring.datasource.p ...
- value(C# )
上下文关键字 value 用在普通属性声明的 set 访问器中. 此关键字类似于方法的输入参数. 关键字 value 引用客户端代码尝试分配给属性的值. 在以下示例中,MyDerivedClass 有 ...
- vue--生命周期演示
vue实例的生命周期:https://cn.vuejs.org/v2/guide/instance.html#%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA-Vue-%E5% ...
- c语言Ι博客作业04
这个作业属于哪个课程 c语言程序设计II 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/CST2019-3/homework/9771 我在这个课程的目 ...
- [转帖]Marvell第二代ARM处理器ThunderX2解析
Marvell第二代ARM处理器ThunderX2解析 https://www.cnbeta.com/articles/tech/853137.htm 长久以来,服务器数据中心市场一直被x86 CPU ...
- HDU-5471 Count the Grid
题目描述 一个矩阵中可以任意填\(m\)个数.给你\(N\)个小矩阵并且告诉你此矩阵中的最大值\(v\),求有多少种大矩阵满足所给条件.\((\%1e9+7)\) Input 包含\(T\)组数据. ...