首先我们先来了解一下什么是重排序:重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段。

从Java源代码到最终实际执行的指令序列,会分别经历下面3种重排序,如下图所示

上述的1属于编译器重排序,2和3属于处理器重排序。这些重排序可能会导致多线程程序出现内存可见性问题。在单线程程序中,对存在控制依赖的操作重排序,不会改变执行结果(这也是as-if-serial语义允许对存在控制依赖的操作做重排序的原因);但在多线程程序中,对存在控制依赖的操作重排序,可能会改变程序的执行结果。

1)数据依赖性(针对单个处理器而已)

关于重排序,这里要先讲一个概念就是数据依赖性问题。如果两个操作访问同一个变量,且这两个操作中有一个为写操作,此时这两个操作之间就存在数据依赖性。数据依赖分为下列3种类型,如下表所示。

上面3种情况,只要重排序两个操作的执行顺序,程序的执行结果就会被改变。前面提到过,编译器和处理器可能会对操作做重排序。编译器和处理器在重排序时,会遵守数据依赖性,编译器和处理器不会改变存在数据依赖关系的两个操作的执行顺序。这里所说的数据依赖性仅针对单个处理器中执行的指令序列和单个线程中执行的操作,不同处理器之间和不同线程之间的数据依赖性不被编译器和处理器考虑。

2)as-if-serial语义

as-if-serial语义的意思是:不管怎么重排序,(单线程)程序的执行结果不能被改变。编译器、runtime和处理器都必须遵守as-if-serial语义。

为了遵守as-if-serial语义,编译器和处理器不会对存在数据依赖关系的操作做重排序。as-if-serial语义把单线程程序保护了起来,as-if-serial语义使单线程程序员无需担心重排序会干扰他们,也无需担心内存可见性问题。

3)happens-before

如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须要存在happens-before关系。这里提到的两个操作既可以是在一个线程之内,也可以是在不同线程之间。

对happens-before关系的具体定义如下。

① 如果一个操作happens-before另一个操作,那么第一个操作的执行结果将对第二个操作可见,而且第一个操作的执行顺序排在第二个操作之前。

②两个操作之间存在happens-before关系,并不意味着Java平台的具体实现必须要按照 happens-before关系指定的顺序来执行。如果重排序之后的执行结果,与按happens-before关系来执行的结果一致,那么这种重排序并不非法(也就是说,JMM允许这种重排序)。

上面的①是JMM对程序员的承诺。从程序员的角度来说,可以这样理解happens-before关系:如果A happens-before B,那么Java内存模型将向程序员保证——A操作的结果将对B可见,且A的执行顺序排在B之前。注意,这只是Java内存模型向程序员做出的保证!上面的②是JMM对编译器和处理器重排序的约束原则。正如前面所言,其实是在遵循一个基本原则:只要不改变程序的执行结果(指的是单线程程序和正确同步的多线程程序),编译器和处理器怎么优化都行。因此,happens-before关系本质上和as-if-serial语义是一回事。

·as-if-serial语义保证单线程内程序的执行结果不被改变,happens-before关系保证正确同步的多线程程序的执行结果不被改变。

·as-if-serial语义给编写单线程程序的程序员创造了一个幻境:单线程程序是按程序的顺序来执行的。happens-before关系给编写正确同步的多线程程序的程序员创造了一个幻境:正确同步的多线程程序是按happens-before指定的顺序来执行的。

· as-if-serial语义和happens-before这么做的目的,都是为了在不改变程序执行结果的前提下,尽可能地提高程序执行的并行度。

happens-before规则如下:

程序顺序规则:一个线程中的每个操作,happens-before于该线程中的任意后续操作。

监视器锁规则:对一个锁的解锁,happens-before于随后对这个锁的加锁。

volatile变量规则:对一个volatile域的写,happens-before于任意后续对这个volatile域的读。

传递性:如果A happens-before B,且B happens-before C,那么A happens-before C。

start()规则:如果线程A执行操作ThreadB.start()(启动线程B),那么A线程的ThreadB.start()操作happens-before于线程B中的任意操作。

join()规则:如果线程A执行操作ThreadB.join()并成功返回,那么线程B中的任意操作happens-before于线程A从ThreadB.join()操作成功返回。

java升序问题_JAVA并发理解之重排序问题相关推荐

  1. java cas机制_java并发编程中的CAS机制,你理解嘛?

    学习Java并发编程,CAS机制都是一个不得不掌握的知识点.这篇文章主要是从出现的原因再到原理进行一个解析.希望对你有所帮助. 一.为什么需要CAS机制? 为什么需要CAS机制呢?我们先从一个错误现象 ...

  2. java lock 对象_Java并发编程锁系列之ReentrantLock对象总结

    Java并发编程锁系列之ReentrantLock对象总结 在Java并发编程中,根据不同维度来区分锁的话,锁可以分为十五种.ReentranckLock就是其中的多个分类. 本文主要内容:重入锁理解 ...

  3. java计算时间差_JAVA并发编程三大Bug源头(可见性、原子性、有序性),彻底弄懂...

    原创声明:本文转载自公众号[胖滚猪学编程]​ 某日,胖滚猪写的代码导致了一个生产bug,奋战到凌晨三点依旧没有解决问题.胖滚熊一看,只用了一个volatile就解决了.并告知胖滚猪,这是并发编程导致的 ...

  4. java动态同步_java并发基础-Synchronized

    基础使用 基本上Java程序员都简单的了解synchronized的使用: 无非就是用在多线程环境下的同步. 看如下简单的例子: publicclassUnsafeCounter{ privatein ...

  5. java线程池_Java 并发编程 线程池源码实战

    作者 | 马启航 杏仁后端工程师.「我头发还多,你们呢?」 一.概述 笔者在网上看了好多的关于线程池原理.源码分析相关的文章,但是说实话,没有一篇让我觉得读完之后豁然开朗,完完全全的明白线程池,要么写 ...

  6. java 变量共享_Java并发编程之共享变量

    可见性 如果一个线程对共享变量值的修改,能够及时的被其他线程看到,叫做共享变量的可见性. Java 虚拟机规范试图定义一种 Java 内存模型(JMM),来屏蔽掉各种硬件和操作系统的内存访问差异,让 ...

  7. java内存 海子_Java并发编程:从根源上解析volatile关键字的实现

    Java并发编程:volatile关键字解析 1.解析概览 内存模型的相关概念 并发编程中的三个概念 Java内存模型 深入剖析volatile关键字 使用volatile关键字的场景 2.内存模型的 ...

  8. java线程安全性_Java并发-线程安全性

    1.什么是线程安全性? 在线程安全性的定义中,最核心的就是正确性.当多线程访问调用某个类时,线程之间不会出现错误的交互,不管运行时线程如何交替执行,并且在主调代码不需要任何同步或协同,这个类都能表现出 ...

  9. java投票锁_Java并发编程锁之独占公平锁与非公平锁比较

    Java并发编程锁之独占公平锁与非公平锁比较 公平锁和非公平锁理解: 在上一篇文章中,我们知道了非公平锁.其实Java中还存在着公平锁呢.公平二字怎么理解呢?和我们现实理解是一样的.大家去排队本着先来 ...

最新文章

  1. 亿级数据湖统一存储技术实践
  2. 《LeetCode力扣练习》剑指 Offer 11. 旋转数组的最小数字 Java
  3. 运维Linux redis,系统运维|如何在 CentOS 7 上安装 Redis 服务器
  4. python写了代码_Python写代码的用法建议
  5. 如何使用XML作为小型数据库
  6. Python通过代理多线程抓取图片
  7. python常量变量和对象_Python学习笔记——变量和常量
  8. Spring Boot 2.0 Intellij Idea 中图文详解打包成可执行Jar
  9. 转【es中数据节点和主机】
  10. Redis 入门文档
  11. android小应用帮美女更衣系列一(附源码)
  12. Vivado下载 安装 与 和谐教程
  13. Mathematical notation
  14. Android 插件化换肤方案
  15. 小丁在研究数学问题时遇到一个定义:对于排好顺序的k个数:x1,x2,x3,…,xk,称为数列Ak:x1,x2,x3,xk,其中k为整数且k≥3.定义V(Ak)=|x1-x2|+|x2-x3|+…+|x
  16. 音视频开发工程师学习之路
  17. SpringBoot安全登录验证
  18. 图片怎么转文字?这些方法值得收藏
  19. 解决多元线性回归的多重共线性问题
  20. A006-AndroidManifest.xml解析

热门文章

  1. HarmonyOS系统概述
  2. MindSpore图像分类模型支持(Lite)
  3. 计算机视觉系列最新论文(附简介)
  4. CoordinatorLayout 和 AppBarLayout 实现的局部点击按钮实现滑动某一个固定的距离
  5. JavaScript Collection
  6. 04:sqlalchemy操作数据库 不错
  7. 关于linux安装前规划分区二三事
  8. PASCAL VOC工具包解读
  9. WebSocket的几个模块(node.js)(未完)
  10. 机器学习入门(21)— 感受野概念