JAVA多线程之先行发生原则
一、引子
如果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多线程之先行发生原则的更多相关文章
- java内存模型—先行发生原则
Java语言中有一个“先行发生”(happens-before)的原则.这个原则非常重要,它是判断数据是否存在竞争,线程是否安全的主要依据,依赖这个原则,我们可以通过几条规则一揽子解决并发环境下两个操 ...
- Java之先行发生原则与volatile关键字详解
volatile关键字可以说是Java虚拟机提供的最轻量级的同步机制,但是它并不容易完全被正确.完整地理解,以至于许多程序员都习惯不去使用它,遇到需要处理多线程数据竞争问题的时候一律使用synchro ...
- 先行发生原则(Happens-before)
先行发生原则(Happens-Before)是判断数据是否存在竞争.线程是否安全的主要依据. 先行发生是Java内存,模型中定义的两项操作之间的偏序关系,如果操作A先行发生于操作B,那么操作A产生的影 ...
- Happens-before先行发生原则
简介 从JDK1.5,java使用新的JSR-133内存模型:JSR-133使用happens-before的概念来阐述操作之间的内存可见性:在JMM中,如果一个操作执行的结果需要对另一个操作可见,那 ...
- 40个Java多线程问题总结
前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...
- Java多线程问题总结
前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...
- [java] 40个Java多线程问题总结
40个问题汇总 1.多线程有什么用? 一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用?在我看来,这个回答更扯淡.所谓"知其然知其所以然","会用 ...
- 40个Java多线程问题
1.多线程有什么用? 一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用?在我看来,这个回答更扯淡.所谓”知其然知其所以然”,”会用”只是”知其然”,”为什么用”才是”知其所以然 ...
- JAVA多线程与并发学习总结
1. 计算机系统 使用高速缓存来作为内存与处理器之间的缓冲,将运算需要用到的数据复制到缓存中,让计算能快速进行:当运算结束后再从缓存同步回内存之中,这样处理器就无需等待缓慢的内存读写了. 缓 ...
随机推荐
- 要不要用gzip优化前端项目
这两天在做项目优化,注意到webpack有一个compression-webpack-plugin插件,可以打包成gzip格式部署到服务器,了解到了GZIP,其实GZIP有很多点,这里我们只讨论前端范 ...
- python机器学习工具包
1. scikit-learn: Machine Learning in Python scikit-learn是一个基于NumPy, SciPy, Matplotlib的开源机器学习工具包,主要涵盖 ...
- 在虚拟机中安装metasploit官方攻防模拟器
首先我们要在windwos下载安装perl环境.下载地址: http://pan.baidu.com/s/1i3GLKAp 然后我们安装 点击next 我同意,next next next,然后他会安 ...
- deeplearning.ai 改善深层神经网络 week3 超参数调试、Batch正则化和程序框架 听课笔记
这一周的主体是调参. 1. 超参数:No. 1最重要,No. 2其次,No. 3其次次. No. 1学习率α:最重要的参数.在log取值空间随机采样.例如取值范围是[0.001, 1],r = -4* ...
- 51nod 1575 Gcd and Lcm
题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1575 万年巨坑终于填掉了…… 首先是煞笔西瓜的做题历程O_O. ...
- [51nod1676]无向图同构
如果一个无向图重标号后与另一个无向图完全一致(即对于任意两点,他们之间的边在两个图中都存在或都不存在),则称两个无向图同构. 给定两个n个点m条边的无向图,判定两个无向图是否同构.不超过20组数据,n ...
- printf不能直接输出string类型
因为string不是c语言的内置数据,所以直接printf输出string类型的是办不到的.要这样输出: printf("%s\n",a.c_str()); 举例: #includ ...
- ES6中promise的使用方法
先看看ES5中异步编程的使用. let ajax = function (callBlack) { setTimeout(function () { callBlack && call ...
- Android 社区App 《窝吧》开源分享
一整个社区模式App的整套代码,包括发布动态,添加.删除好友,添加黑名单,聊天,用户反馈等功能. 相关技术 1 底层使用Bmob后端云,官网: https://www.bmob.cn/ 2 友盟插件, ...
- JavaScript八张思维导图—Date用法
JS基本概念 JS操作符 JS基本语句 JS数组用法 Date用法 JS字符串用法 JS编程风格 JS编程实践 不知不觉做前端已经五年多了,无论是从最初的jQuery还是现在火热的Angular,Vu ...