Java 多线程 -- 指令重排(HappenBefore)
指令重排是指:代码执行顺序和预期不一致。
代码运行一般步骤为:
1、从内存中获取指令解码
2、计算值
3、执行代码操作
4、把结果写回内存
而写回内存的操作比较耗时,CPU为了性能,可能不会等它完成,就进行对下一个指令解码计算。
发生指令重排是CPU为了提高性能,但必须是对结果不影响的情况,比如:
a =1; b =2; 先计算a 或者 b 对结果来说没有影响,就有肯能发送重排;而像 a = 5; b = a*3;这样的代码则不会发生重排。
一把发生指令重排在单线程中基本没啥影响,当时在多线程中,同时操作一个数据,如果一个读,一个写,当写的线程还没写回时,另一个线程已经开始读取了,那么这个时候就会出现和预期不一致的结果。
写一个可能生指令重排的代码:
public class HappenBefore {
private static int a = 0;
private static boolean flag = false;
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
a = 0;
flag = false;
// 线程1 更改数据
Thread t1 = new Thread(() -> {
a = 1;
flag = true;
});
// 线程2 读取数据
Thread t2 = new Thread(() -> {
if (flag) {
a *= 1;
}
if (a == 0) {
System.out.println("指令重排了-->" + a);
}
});
t1.start();
t2.start();
// 合并线程,让更改数据线程先运行完
t1.join();
t2.join();
}
}
}
运行以上代码:

我的电脑配的是最新的4代内存,运行10次,发生两次指令重排,如果用的是老一代的内存条,发生几率应该是会大一些。
Java 多线程 -- 指令重排(HappenBefore)的更多相关文章
- Java中指令重排
/** * 指令重排:代码执行顺序与预期不一致 (发生在前后行代码无联系时) * 目的:提高性能 * */ public class HappenBefore { private static int ...
- Java内存模型与指令重排
Java内存模型与指令重排 本文暂不讲JMM(Java Memory Model)中的主存, 工作内存以及数据如何在其中流转等等, 这些本身还牵扯到硬件内存架构, 直接上手容易绕晕, 先从以下几个点探 ...
- JMM内存模型、CPU缓存一致性原则(MESI)、指令重排、as-if-serial、happen-before原则
JMM三大特性原子性 汇编指令 --原子比较和交换在底层的支持 cmp-chxg 总线加锁机制 Synchronized Lock锁机制 public class VolatileAtomicSamp ...
- 多线程的指令重排问题:as-if-serial语义,happens-before语义;volatile关键字,volatile和synchronized的区别
一.指令重排问题 你写的代码有可能,根本没有按照你期望的顺序执行,因为编译器和 CPU 会尝试指令重排来让代码运行更高效,这就是指令重排. 1.1 虚拟机层面 我们都知道CPU执行指令的时候,访问内存 ...
- 【java多线程系列】java内存模型与指令重排序
在多线程编程中,需要处理两个最核心的问题,线程之间如何通信及线程之间如何同步,线程之间通信指的是线程之间通过何种机制交换信息,同步指的是如何控制不同线程之间操作发生的相对顺序.很多读者可能会说这还不简 ...
- Java并发编程(五)JVM指令重排
我是不是学了一门假的java...... 引言:在Java中看似顺序的代码在JVM中,可能会出现编译器或者CPU对这些操作指令进行了重新排序:在特定情况下,指令重排将会给我们的程序带来不确定的结果.. ...
- Java并发:volatile内存可见性和指令重排
volatile两大作用 1.保证内存可见性 2.防止指令重排 此外需注意volatile并不保证操作的原子性. (一)内存可见性 1 概念 JVM内存模型:主内存和线程独立的工作内存 Java内存模 ...
- Java 指令重排
Java 指令重排 java 指令重排 package com.feshfans; /** * 用来演示指令重排 * 指令重排会发生在两个阶段: * 1. 编译期(jvm 加载字节码时) * 2. c ...
- 一篇讲Java指令重排和内存可见性的好文
在这里: http://tech.meituan.com/java-memory-reordering.html 指令重排和内存可见性(缓存不一致)是两个不同的问题. volatile关键字太强,即阻 ...
随机推荐
- FME中按照ID值过滤块参照中的多个要素
- 高性能RabbitMQ
1,什么是RabbitMq RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件).RabbitMQ服务器是用Erlang语言编写的,而集群和故障转移是构建在开 ...
- HBase Shell Get 操作常用小技巧
在工作中,有时候只是想简单看下HBase表某些关键指标的值,这个时候总不能现写Java代码去查看,以下几个小技巧你可能会经常用到. 1. 某行有许多列,只想获取指定2~3列的数据 hbase> ...
- 学习 MyBatis 的一点小总结 —— 底层源码初步分析
目录 MyBatis 如何获取数据库源? MyBatis 如何获取 sql 语句? MyBatis 如何执行 sql 语句? MyBatis 如何实现不同类型数据之间的转换? 在过去程序员使用 JDB ...
- 双连通分量 Road Construction POJ - 3352
@[双连通分量] 题意: 有一个 n 个点 m 条边的无向图,问至少添加几条边,能让该图任意缺少一条边后还能相互连通. 双连通分量定义: 在无向连通图中,如果删除该图的任何一个结点都不能改变该图的连通 ...
- Scala环境及IDEA配置
Scala环境及IDEA配置 1 语言介绍 他已经出生15年了,就像明星一样,谁都不可能一开始就人气爆棚粉丝无数,得慢慢混. 成功原因:完全兼容java代码. 身世介绍 Scala在2004年正式问世 ...
- Activiti7新的API介绍
一.Activiti7 的组成部分 Activiti Core 作为Activiti 的核心部分,Activiti Cloud 主要是利用云服务来实现分布式业务流程开发. 二.Activiti 新的 ...
- ARM.SchDoc图解
1.基准电压.CR1220电池 2.LCD 3.SPI 4.外部SAM 5.实时时钟 6.EEPROM 7.JTAG 8.复位
- Netty:Channel
上一篇我们通过一个简单的Netty代码了解到了Netty中的核心组件,这一篇我们将围绕核心组件中的Channel来展开学习. Channel的简介 Channel代表着与网络套接字或者能够进行IO操作 ...
- Vlan间通讯,动态路由
Vlan间通讯,动态路由 案例1:三层交换vlan间通信 案例2:多交换机vlan间通信 案例3:三层交换配置路由 案例4:RIP动态路由配置 案例5:三层交换配置RIP动态路由 1 案例1:三层交换 ...