前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java虚拟机--先行发生原则

Java虚拟机--先行发生原则

作者头像
SuperHeroes
发布2018-05-22 16:28:25
4810
发布2018-05-22 16:28:25
举报
文章被收录于专栏:云霄雨霁云霄雨霁

上一篇:Java虚拟机--内存模型

如果Java内存模型中所有有序性都靠volatile和synchronized来完成,那么编写代码会很繁琐,但日常Java开发中并没有感受到这一点,正是因为Java语言的“先行发生”原则。这个原则非常重要,它是判断数据是否存在竞争、线程是否安全的主要依据。

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

下面是Java内存模型中一些“天然的”先行发生关系,这些先行发生关系无需任何同步协助器协作即可存在,可以直接在编码中使用。如果两个关系不在此列,而又无法通过这些关系推导出来,它们的顺序就无法保证,虚拟机可以对它们任意重排序。

  1. 程序次序规则 :一个线程内,按照程序代码的顺序,书写在前面的操作先行发生于(逻辑上)书写在后面的操作。 
  2. 管程锁定规则 :一个unlock操作先行发生于后面对同一个锁的lock操作。后面指时间上的先后顺序。 
  3. volatile变量规则 :对一个volatile变量的写操作先行发生于后面对这个变量的读操作。这里的后面指时间上的先后顺序。 
  4. 线程启动规则 :Thread对象的start方法先行发生于此线程的每个动作; 
  5. 线程终止规则 :线程中的所有操作都先行发生于对此线程的终止检测; 
  6. 线程中断规则 :对线程的interrupt()方法的调用先行发生于被中断线程的代码检测到中断时间的发生; 
  7. 对象终结规则 :一个对象的初始化完成先行发生于它的finalize方法的开始; 
  8. 传递性 :如果操作A先行发生于操作B,操作B先行发生于操作C,那么,操作A也就先行发生于操作C。 

java无须任何手段即可保证上面的先行发生规则成立,下面那个例子看一下:

代码语言:javascript
复制
private int value = 0;

public void setValue(int value){
    this.value = value;
}

public int getValue(){
    return value;
}

假设线程A先(时间上的先后)执行setValue(1), 然后线程B调用同一对象的getValue(),那么线程B收到的返回值是什么?

依次分析一下先行发生原则中的各个原则:由于两个方法分别在不同的线程中被调用,程序次序原则不适用;没有同步块,自然不会发生lock和unlock操作,管程锁定原则不适用;value变量没有被volatile修饰,volatile变量原则不适用;后面的线程启动、中断、终止原则也毫无关系;没有一个适用的原则,传递性也不适用。所以说线程B得到的结果不确定是0还是1,换句话说,这里面的操作不是线程安全的。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 上一篇:Java虚拟机--内存模型
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档