在执行程序时为了提高性能,提高并行度,编译器和处理器常常会对指令做重排序。重排序分三种类型:

  1. 编译器优化的重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。
  2. 指令级并行的重排序。现代处理器采用了指令级并行技术(Instruction-Level Parallelism, ILP)来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。
  3. 内存系统的重排序。由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。

问题:重排序都可能会导致多线程程序出现内存可见性问题

1)编译器优化的重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。

2)指令级并行的重排序。处理器多条指令重叠执行,改变语句对应机器指令的执行顺序(处理器重排)

3)内存系统的重排序。处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行(处理器重排)

举例:处理器对内存的读/写操作的执行顺序,不一定与内存实际发生的读/写操作顺序一致,导致重排序导致内存可见性问题

  (处理器使用写缓冲区来临时保存向内存写入的数据:避免由于处理器停顿下来等待向内存写入数据而产生的延迟

  以批处理的方式刷新写缓冲区,以及合并写缓冲区中对同一内存地址的多次写,可以减少对内存总线的占用)

假设处理器A和处理器B按程序的顺序并行执行内存访问,最终却可能得到x = y = 0的结果

第一步执行A1 B1

第二步执行A2 B2,此时已得到x=b=0 y=a=0

第三步执行A3 B3

执行完A3,A1才算执行完,A1 A2重排序了

JMM通过禁止特定类型的编译器重排序和处理器重排序,为程序员提供一致的内存可见性保证

JMM的编译器重排序规则会禁止特定类型的编译器重排序

java编译器在生成指令序列时,插入特定类型的内存屏障指令来禁止特定类型的处理器重排序

Java并发(三):重排序的更多相关文章

  1. Java内存访问重排序笔记

    >>关于重排序 重排序通常是编译器或运行时环境为了优化程序性能而采取的对指令进行重新排序执行的一种手段. 重排序分为两类:编译期重排序和运行期重排序,分别对应编译时和运行时环境. > ...

  2. java基础之 重排序

    重排序通常是编译器或运行时环境为了优化程序性能而采取的对指令进行重新排序执行的一种手段.重排序分为两类:编译期重排序和运行期重排序,分别对应编译时和运行时环境. 在并发程序中,程序员会特别关注不同进程 ...

  3. java内存模型——重排序

    线程安全问题概括来说表现为三个方面:原子性,可见性和有序性. 在多核处理器的环境下:编译器可能改变两个操作的先后顺序:处理器可能不是完全依照程序的目标代码所指定的顺序执行命令:一个处理器执行的多个操作 ...

  4. java内存模型-重排序

    数据依赖性 如果两个操作访问同一个变量,且这两个操作中有一个为写操作,此时这两个操作之间就存在数据依赖性.数据依赖分下列三种类型: 名称 代码示例 说明 写后读 a = 1;b = a; 写一个变量之 ...

  5. Java并发(三):实例引出并发应用场景

    前两篇介绍了一些Java并发的基础知识,博主正巧遇到一种需求:查询数据库,根据查询结果集修改数据库记录,但整个流程是做成了一个schedule的,并且查询比较耗时,并且需要每两分钟执行一次,cpu经常 ...

  6. 探索JAVA并发 - 可重入锁和不可重入锁

    本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...

  7. java 并发(三)---Thread 线程

    Thread 的状态 线程共有五种状态.分别是: (1)新建 (2)就绪 (3)运行 (4)阻塞 (5)死亡 ,下面列列举的状态需要结合状态示意图更好理解.  新建状态(New): 新创建了一个线程对 ...

  8. Java并发:重入锁 ReentrantLock(二)

    一.理解锁的实现原理 1. 用wait()去实现一个lock方法,wait()要和synchronized同步关键字一起去使用的,直接使用wait方法会直接报IllegalMonitorStateEx ...

  9. Java并发:重入锁 ReentrantLock(一)

    ReentrantLock 是一种可重入的互斥锁,它不像 synchronized关键字一样支持隐式的重进入,但能够使一个线程(不同的方法)重复对资源的重复加锁而不受阻塞. ReentrantLock ...

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

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

随机推荐

  1. Python 开发中easy_install的安装及使用

    easy_install是一个python的扩展包,主要是用来简化python安装第三方安装包,在安装了easy_install之后,安装python第三方安装包就只需要在命令行中输入:easy_in ...

  2. 新建一个express工程,node app无反应

    1.问题描述 新建一个express工程,node app以后无反应,浏览器输入localhost:3000,显示如下 2.解决方法 在app.js文件中加入如下代码 app.listen(3000, ...

  3. css position的值

    值 描述 absolute 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位. 元素的位置通过 "left", "top", " ...

  4. const 引用的分析

    const 引用: 在初始化常量引用时,允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可.尤其,允许为一个常量引用绑定非常量的对象.字面值,甚至是一个表达式.我们来看 const ...

  5. Python——turtle生成图片保存

    代码示例如下: from Tkinter import * from turtle import * import turtle forward(100) ts = turtle.getscreen( ...

  6. RabbitMQ 实践及使用

    目录 - 1. RabbitMQ的安装    - 1.1 配置好 epel    - 1.2 安装 RPM包    - 1.3 创建用户设置权限- 2. RabbitMQ组件- 3. RabbitMQ ...

  7. Hibernate检索策略与检索方式

    hibernate的Session在加载Java对象时,一般都会把鱼这个对象相关联的其他Java对象也都加载到缓存中,以方便程序的调用.但很多情况下,我们不需要加载太多无用的对象到缓存中,一来会占用大 ...

  8. mysql数据库隔离级别

    # 原创,转载请留言联系 事务的隔离级别 (由高到低)1.串行化(serializable):一个事务一个事务的执行2.可重复读(Repeatable-Read) 可重复读,无论其他事务是否修改并提交 ...

  9. Commons CLI 学习(1)

    The Apache Commons CLI library provides an API for parsing command line options passed to programs. ...

  10. NOIP模拟2017.6.11解题报告

    T1: 水题: 代码: #include <cstdio> #include <iostream> #include <algorithm> using names ...