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关键字太强,即阻 ...
随机推荐
- Springboot + Freemarker(一)
Maven pom文件配置 <parent> <groupId>org.springframework.boot</groupId> <artifactId& ...
- JavaScript登录记住密码操作
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...
- Oracle给权限和同义词
在同一个DB下,用户A创建了一个Table(student),用户B无法访问.如果B想要访问,就需要A赋予B权限. 登录用户A执行下面语句: GRANT SELECT, INSERT, UPDATE, ...
- Linux基础:Day03
Linux的网络 以太网的发明--PC之间文件共享情况出现 网卡硬件设备 -- MAC地址 一层:物理层 HUB -- 集线器 总线型结构 泛洪 广播域/冲突域 二层: 在早期的网络中,PC互通 ...
- java仿win7计算器布局
代码: package calculator; import javax.swing.*; import java.awt.*; import java.awt.event.*; public cla ...
- 微信小程序--分享功能
微信小程序--分享功能 微信小程序前段时间开放了小程序右上角的分享功能, 可以分享任意一个页面到好友或者群聊, 但是不能分享到朋友圈 这里有微信开发文档链接:点击跳转到微信分享功能API 入口方法: ...
- 如何增加Tomcat内存
有时候在开发中,常常遇到内存溢出问题,很有可能项目过大,导致Tomcat内存不足问题,那么此时就要给Tomcat添加内存了,如,操作如下 1. 先找到Tomcat目录下的catalina.bat文件
- Struts2-学习笔记系列(6)-动态调用action
动态调用之前需要配置: <!--动态方法调用--> <constant name="struts.enable.DynamicMethodInvocation" ...
- ASP.NET Core 3.1+MySQL 部署到docker上面使用docker-compose+DockerFile
一.新建DockerFile文件 选择Linux版本 FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base WORKDIR ...
- Fiddler实战之拟2G、3G、4G网络进行弱网测试
至于fidder网络代理设置就不多说了 模拟网速: 1.启动Fiddler,打开菜单栏Rules---Performances---Simulate Modem Speeds这里打开了模拟调节速度 2 ...