一、引子  

  如果java内存模型中所有的有序性都仅仅依靠volatile和synchronized来完成,那么有一些操作会变得很繁琐,但我们在编写java并发代码时并未感觉到这一点,这是因为java语言中有个先行发生原则(happens-before),通过这个原则,我们可以通过几条规则一揽子解决并发环境下两个操作之间是否可能存在冲突的所有问题。

二、定义

  先行发生是java内存模型中定义的两项做错之间的偏序关系,如果说操作A先行发生与操作B,其实就是说在发生操作B之前,操作A产生的影响能被操作B观察到,“影响”包括修改了内存中共享变量的值、发送了消息、调用了方法等。

三、规则
  java内存模型中“天然的”的先行发生关系规则如下:
  1、程序次序规则:
    在一个线程内,按照程序代码顺序,,书写在前面的操作先行发生于书写在后面的操作,准确的说,应该是控制流程序而不是程序代码顺序,因为要考虑分支、循环等结构;
  2、管程锁规则:
    一个unlock操作先行发生于后面对同一个锁的lock操作,这里必须强调的是同一个锁,“后面”指的是时间上的先后顺序。
  3、volatile变量规则:
    对一个volatile变量的写操作先行发生于后面对这个变量的读操作,“后面”同样是时间上的先后顺序。
  4、线程启动规则:
    Thread对象的start()方法先行发生于次线程的每一个动作;
  5、线程终止规则:
    线程中的所有操作都先行发生于对此线程的终止检测,可以通过Thread.join()方法结束,Thread.isAlive()的返回值等手段检测到线程已终止执行
  6、线程中断规则:
    对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生,可以通过Thread.interruptd()方法检测到是否有中断发生
  7、对象终结规则:
    一个对象的初始化完成(构造函数执行结束)先行发生于它的finalize()方法的开始
  8、传递性
    如果操作A先行发生于操作B,操作B先行发生于操作C,那么就可以认为操作A先行发生于操作C。

四、示例  

如下案例:

public class TestValue {
private int value = 0; public int getValue() {
return value;
} public void setValue(int value) {
this.value = value;
}
}

  如果线程A调用了“setValue(1)”,线程B调用了同一个对象的“getValue()”方法,那么返回值是什么?
    答案是不确定,因为这里的操作不是线程安全的,它不满足上述所有的 先行发生 规则。
  修复方法有好多种,这里列举较为简单的两种:
  1)把getter/setter方法都定义为synchronized方法
  2)把value定义为volatile变量。

JAVA多线程之先行发生原则的更多相关文章

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

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

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

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

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

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

  4. Happens-before先行发生原则

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

  5. 40个Java多线程问题总结

    前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...

  6. Java多线程问题总结

    前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...

  7. [java] 40个Java多线程问题总结

    40个问题汇总 1.多线程有什么用? 一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用?在我看来,这个回答更扯淡.所谓"知其然知其所以然","会用 ...

  8. 40个Java多线程问题

    1.多线程有什么用? 一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用?在我看来,这个回答更扯淡.所谓”知其然知其所以然”,”会用”只是”知其然”,”为什么用”才是”知其所以然 ...

  9. JAVA多线程与并发学习总结

    1.      计算机系统 使用高速缓存来作为内存与处理器之间的缓冲,将运算需要用到的数据复制到缓存中,让计算能快速进行:当运算结束后再从缓存同步回内存之中,这样处理器就无需等待缓慢的内存读写了. 缓 ...

随机推荐

  1. Luogu P1231 教辅的组成

    Luogu P1231 教辅的组成 题目背景 滚粗了的HansBug在收拾旧语文书,然而他发现了什么奇妙的东西. 题目描述 蒟蒻HansBug在一本语文书里面发现了一本答案,然而他却明明记得这书应该还 ...

  2. linux(六)之文本操作

    接下来我们一起来看一下再linux中怎么去对文本进行操作的 一.文本文件 既然要操作文本,所以我们要对文本有一个了解,那什么是文本文件呢. 文本文件是一种由若干行字符构成的计算机文件.文本文件存在于计 ...

  3. Eclipse安装svn插件的几种方式 转帖....

    Eclipse安装svn插件的几种方式 1.在线安装: (1).点击 Help --> Install New Software... (2).在弹出的窗口中点击add按钮,输入Name(任意) ...

  4. [国嵌笔记][029][ARM处理器启动流程分析v2]

    2440启动流程 启动方式:nor flash启动.nand flash启动 地址布局: 选择nor flash启动时,SROM(nor flash)地址为0x00000000 选择nand flas ...

  5. 2017-6-14 踩坑小结(Android文件读写 相关问题)

    填坑 getSlotFromBufferLocked: unknown buffer: 0xab7115e0 1. 在棉花糖(6.0)上莫名出现 未知缓冲 错误,百度了一下,貌似这个是Android6 ...

  6. centos 6.4 mysql rpm 离线安装【备忘】

    离线状态下使用rpm的安装包进行mysql的安装,仅作备忘 准备工作: 官网下载mysql离线rpm安装包(这里就不演示了,拿现成的做演示) =================更新线 2018-01- ...

  7. 自己动手实现一个简单的JSON解析器

    1. 背景 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.相对于另一种数据交换格式 XML,JSON 有着诸多优点.比如易读性更好,占用空间更少等.在 ...

  8. 主题:Windows系统服务器磁盘挂载

    可能很多人发现VPS重装之后D盘.E盘不见了,其实并没有不见只是磁盘未挂载,下面由小编来为大家讲讲如何挂载磁盘 远程登录服务器后,桌面上只有一个回收站的,我们在桌面空白处右键属性-->桌面--& ...

  9. DEDECMS去掉自动生成首页或栏目后面带的index.html

    Dede默认生成首页后,首页的链接后面会多出一个index.html.据官方说法这样有利于网站优化.但是这个index.html怎么看都不舒服,而且也不利于seo中主页url的统一.因为我的网站的ur ...

  10. dede添加会员功能听语音

    http://jingyan.baidu.com/article/363872ec36d33f6e4ba16fb7.html 其实 dede里面的 会员功能就是圈子模版啦 圈子 安装了 基本上有 1, ...