本文中需要的基础知识:指令重排

线程中两个非常重要的问题就是:原子性与可见性.

而下面的先行发生原则就是用来解决可见性问题的.

先行发生原则--是判断是否存在数据竞争、线程是否安全的主要依据。

先行发生是Java内存模型中定义的两项操作之间的偏序关系。如果说操作A先行发生于操作B,其实就是说在发生操作B之前,操作A产生的影响被操作B察觉。

以下面的一段伪代码为例:

//以下操作在线程A中执行
int i = 1; //以下操作在线程B中执行
j = i; //以下操作在线程C中执行
i = 2

由于线程执行的先后顺序不同,会导致最后j 的结果出现差异。若使线程安全,那么A先行发生B,B先行发生C。

线程B可能获取的是一些过期的数据。故线程不安全!

但是在Java内存模型中确实存在一些已经存在的先行发生关系,这些先行发生关系不需要任何的同步操作,就可以保证其线程安全!

1、程序次序规则在一个线程内,书写在前面的代码先行发生于后面的。确切地说应该是,按照程序的控制流顺序,因为存在一些分支结构。

2、Volatile变量规则对一个volatile修饰的变量,对他的写操作先行发生于读操作。

3、线程启动规则。Thread对象的start()方法先行发生于此线程的每一个动作。

4、线程终止规则。线程的所有操作都先行发生于对此线程的终止检测。

5、线程中断规则。对线程interrupt()方法的调用先行发生于被中断线程的代码所检测到的中断事件。

6、对象终止规则。一个对象的初始化完成(构造函数之行结束)先行发生于发的finilize()方法的开始。

7、传递性A先行发生B,B先行发生C,那么,A先行发生C。

8、管程锁定规则。一个unlock操作先行发生于后面对同一个锁的lock操作。

以上就是Java无需任何的同步手段就能成立的先行发生规则。其他情况下就没有顺序保障,虚拟机可以对它们随意地进行重排序。

总结:

  happens-before指的是前面发生的操作的结构对于后面的操作的结果都是可见的,而在真正操作中并不一定前面的操作就先进行.

执行E的时候,E是不是保证看见C呢? 
由法则1,hb(D,E) 
由法则8,hb(B,D) 
由法则1, hb(A,B) 
综上可以推出,hb(A, E),但是推不出hb(C, E) 
所以,E不一定能看见C,但是E一定能看见A,所以执行E的时候,有可能thread2看到的x的值还是1

  

JVM-- 先行发生原则的更多相关文章

  1. JAVA多线程之先行发生原则

    一.引子 如果java内存模型中所有的有序性都仅仅依靠volatile和synchronized来完成,那么有一些操作会变得很繁琐,但我们在编写java并发代码时并未感觉到这一点,这是因为java语言 ...

  2. java内存模型—先行发生原则

    Java语言中有一个“先行发生”(happens-before)的原则.这个原则非常重要,它是判断数据是否存在竞争,线程是否安全的主要依据,依赖这个原则,我们可以通过几条规则一揽子解决并发环境下两个操 ...

  3. 先行发生原则(Happens-before)

    先行发生原则(Happens-Before)是判断数据是否存在竞争.线程是否安全的主要依据. 先行发生是Java内存,模型中定义的两项操作之间的偏序关系,如果操作A先行发生于操作B,那么操作A产生的影 ...

  4. Java之先行发生原则与volatile关键字详解

    volatile关键字可以说是Java虚拟机提供的最轻量级的同步机制,但是它并不容易完全被正确.完整地理解,以至于许多程序员都习惯不去使用它,遇到需要处理多线程数据竞争问题的时候一律使用synchro ...

  5. Happens-before先行发生原则

    简介 从JDK1.5,java使用新的JSR-133内存模型:JSR-133使用happens-before的概念来阐述操作之间的内存可见性:在JMM中,如果一个操作执行的结果需要对另一个操作可见,那 ...

  6. jvm调优原则

    合理规划jvm性能调优 JVM性能调优涉及到方方面面的取舍,往往是牵一发而动全身,需要全盘考虑各方面的影响.但也有一些基础的理论和原则,理解这些理论并遵循这些原则会让你的性能调优任务将会更加轻松.为了 ...

  7. 【java虚拟机】jvm调优原则

    转自:https://www.cnblogs.com/xiaopaipai/p/10522794.html 合理规划jvm性能调优 JVM性能调优涉及到方方面面的取舍,往往是牵一发而动全身,需要全盘考 ...

  8. JVM 中发生内存溢出的 8 种原因及解决办法

    1. Java 堆空间 2. GC 开销超过限制 3. 请求的数组大小超过虚拟机限制 4. Perm gen 空间 5. Metaspace 6. 无法新建本机线程 7. 杀死进程或子进程 8. 发生 ...

  9. Java中new一个对象是一个怎样的过程?JVM中发生了什么?

    Java中new一个对象的步骤: 1. 当虚拟机遇到一条new指令时候,首先去检查这个指令的参数是否能 在常量池中能否定位到一个类的符号引用 (即类的带路径全名),并且检查这个符号引用代表的类是否已被 ...

随机推荐

  1. HDU - 2276 Kiki & Little Kiki 2

    Description There are n lights in a circle numbered from 1 to n. The left of light 1 is light n, and ...

  2. map的erase()释放内存

    STL中的map调用erase(it),当value值为指针时,释放内存: #include <iostream> #include <map> #include <st ...

  3. javaEE的13种核心技术规范

    javaEE平台由一整套服务(Services).应用程序接口(APIs)和协议构成,它对开发基于Web的多层应用提供了功能支持,下面对javaEE中的13种技术规范进行简单的记录:   J2EE中的 ...

  4. centos 6.4 FTP安装和配置

    链接地址:http://blog.csdn.net/wind520/article/details/38019647 1: 安装 检查是否安装 [root@localhost ~]# rpm -qa ...

  5. ThinkPHP 常用配置项列表

    //数据库配置 DB_HOST 主机名 DB_USER 用户名 DB_PWD 密码 DB_NAME 数据库名 DB_PREFIX 表前缀 LOAD_EXT_FILE=>'function lis ...

  6. win64位 apache2.4 php5.4 mysql5.6

    apache2.4 php5.4 mysql5.6 源文件下载 +以前的配置数据参考 链接:http://pan.baidu.com/s/1skfmGyT 密码:hqtp 比较好的参考资料 http: ...

  7. dlib库学习之一

    dlib库学习之一 1.介绍 跨平台 C++ 通用库 Dlib 发布 ,带来了一些新特性,包括概率 CKY 解析器,使用批量同步并行计算模型来创建应用的工具,新增两个聚合算法:中国低语 (Chines ...

  8. 数组排序-Objectivec

    发表于昨天(23:33)(2013-11-03 23:33) ,已有15次阅读 ,共0个评论 摘要: 总结OC中数组排序3种方法:sortedArrayUsingSelector:;sortedArr ...

  9. S2S:分享出的营销机遇

    (速途网专栏 作者:高学争)经常在网上购物的你,有没有遇到过这样的问题:你知道自己想买什么,但是在淘宝上一搜,出来了数以万计的同类型,他们有着同样的价位(甚至可能是同样的图片),但是由不同的商家提供, ...

  10. 【转】C++常见错误大全

    原文转自:http://hi.baidu.com/qiou2719/item/b9eed949130ff50ec0161331 C++常见错误大全 0. XXXX "is not a cla ...