Java内存模型是通过各种操作来定义的,包括对变量的读/写操作,监视器的加锁和释放操作,以及线程的启动和合并操作。JMM为程序中所有的操作定义了一个偏序关系,称之为Happens-Before。要想保证执行操作B的线程看到操作A的结果(无论A和B是否在同一个线程中执行),那么A和B之间必须满足Happens-Before关系。如果两个操作之间缺乏Happens-Before关系,那么JVM可以对它们任意地重排序。

  当一个变量被多个线程读取并且至少被一个线程写入时,如果在读操作和写操作之间没有按照Happens-Before来排序,那么就会产生数据竞争问题。在正确同步的程序中不存在数据竞争,并会表现出串行一致性,这意味着程序中的所有操作都会按照一种固定的和全局的顺序执行。

Happens-Before规则:

  • 程序顺序规则:如果程序中操作A在操作B之前,那么线程中A操作将在B操作之前执行。
  • 监视器锁规则:对一个锁的解锁操作必须在随后对这个锁的加锁操作之前执行。
  • volatile变量规则:对volatile变量的写入操作必须在对该变量的读操作之前执行。
  • 线程启动规则:在线程上对Tread.start()的调用必须在该线程中执行任何操作之前执行。
  • 线程结束规则:线程中的任何操作都必须在其他线程中检测到该线程已经结束之前执行,或者从Thread.join()中成功返回,或者在调用Thread.isAlive()时返回false。
      • 如果线程A执行操作ThreadB.join()并成功返回,那么线程B中的任意操作在线程A从ThreadB.join()操作成功返回之前执行。
  • 中断规则:当一个线程在另一个线程上调用interrupt()时,必须在被中断线程检测到interrupt()调用之前执行。(通过抛出InterruptException,或者调用isInterrupted和interrupted)
  • 终结器规则:对象的构造函数必须在启动该对象的终结器(finalize())之前执行完成。
  • 传递性:如果操作A在操作B之前执行,并且操作B在操作C之前执行,那么操作A必须在操作C之前执行。

  两个线程在使用同一个锁进行同步时,在它们之间的Happens-Before关系:在县城A内部的所有操作都按照它们在源程序中的先后顺序来排序,在线程B内部的操作也是如此。由于A释放了锁M,并且B随后获取了锁M,因此A中所有在释放锁之前的操作,也就位于B中请求锁之后的所有操作之前。

  如果这两个线程是在不同的锁上进行同步的,那么就不能推断出他们之间的动作顺序,因为在这两个线程的操作之间并不存在Happens-Before关系。

Happens-Before原则的更多相关文章

  1. javascript的api设计原则

    前言 本篇博文来自一次公司内部的前端分享,从多个方面讨论了在设计接口时遵循的原则,总共包含了七个大块.系卤煮自己总结的一些经验和教训.本篇博文同时也参考了其他一些文章,相关地址会在后面贴出来.很难做到 ...

  2. 让姑姑不再划拳 码农也要有原则 : SOLID via C#

    “姑娘,别这样.我们是有原则的.” “一个有原则的程序猿是不会写出 “摧毁地球” 这样的程序的,他们会写一个函数叫 “摧毁行星”而把地球当一个参数传进去.” “对,是时候和那些只会滚键盘的麻瓜不同了, ...

  3. java面向对象六原则一法则

    1. 单一职责原则:一类只做它该做的事. 2. 里氏替换原则:子类必须能够替换基类(父类),否则不应当设计为其子类. 3. 依赖倒换原则:设计要依赖于抽象而不是具体化. 4. 接口隔离原则:接口要小而 ...

  4. SOLID 设计原则

    SOLID 原则基本概念: 程序设计领域, SOLID (单一功能.开闭原则.里氏替换.接口隔离以及依赖反转)是由罗伯特·C·马丁在21世纪早期 引入的记忆术首字母缩略字,指代了面向对象编程和面向对象 ...

  5. Java程序员应该了解的10个面向对象设计原则

    面向对象设计原则: 是OOPS(Object-Oriented Programming System,面向对象的程序设计系统)编程的核心,但大多数Java程序员追逐像Singleton.Decorat ...

  6. Atitit.研发团队的管理原则---立长不立贤与按资排辈原则

    Atitit.研发团队的管理原则---立长不立贤与按资排辈原则 1. 组织任命原则概述1 2. 历史的角度看,大部分组织使用的立长不立贤原则1 3. 论资排辈 立长不立贤原则1 3.1. 资格和辈分是 ...

  7. DIP原则、IoC以及DI

    一.DIP原则 高层模块不应该依赖于底层模块,二者都应该依赖于抽象. 抽象不应该依赖于细节,细节应该依赖于抽象. 该原则理解起来稍微有点抽象,我们可以将该原则通俗的理解为:"依赖于抽象&qu ...

  8. TDD原则

    TDD 介绍 测试驱动开发,或者叫 TDD,是一个敏捷方法,通过确保在代码是先前手动编写测试用 例,用测试来驱动开发,从而翻转开发生命周期(它不只是作为一种校验工具). TDD 的原则很简单的: 只有 ...

  9. 【PRINCE2是什么】PRINCE2认证之七大原则(7)

    我们先来回顾一下,PRINCE2七大原则分别是持续的业务验证,经验学习,角色与责任,按阶段管理,例外管理,关注产品,剪裁 第七个原则:根据项目环境剪裁 PRINCE2的价值在于它是一个通用的项目管理方 ...

  10. 【PRINCE2是什么】PRINCE2认证之七大原则(6)

    我们先来回顾一下,PRINCE2七大原则分别是持续的业务验证,经验学习,角色与责任,按阶段管理,例外管理,关注产品,剪裁 第六个原则:关注产品 PRINCE2指出,一个成功的项目必须以产品为导向,而不 ...

随机推荐

  1. get_client_ip()

    get_client_ip()获取ip地址,在开启IPv6协议的主机上会全部返回0.0.0.0原因是他会把ipv6地址认为是非法地址而转换成0.0.0.0,而ipv4地址在ipv6主机上用get_cl ...

  2. Oracle阻塞会话源头查找-单机和RAC环境

    在写 Oracle session相关数据字典(一)  这篇文章时,提到使用v$session视图的树形查询可以得到Oracle锁树,这样就便于我们找出阻塞会话的源头,但是仅仅可以在单机环境中使用.今 ...

  3. template标签介绍和使用

    template标签介绍和使用 1.介绍:template标签是html5新出来的标签,具有3个特点,(1)随意性:可以写在页面中的任何地方.(2)不可见性:它里面的元素都是不可见的.(3)页面也不会 ...

  4. vue使用IntersectionObserver实现无限下拉信息流

    基于 IntersectionObserver 异步监听方法,实现无线信息流下拉加载, https://developer.mozilla.org/zh-CN/docs/Web/API/Interse ...

  5. [SD心灵鸡汤]001.每月一则 - 2015.05

    1.既然我的父母不能带给我荣耀,那我要做的就只是带给我的子女荣耀,而不是无聊的嫉妒眼红别人. 2.就人生游戏讲,男人是女人的玩物,女人是魔鬼的玩物.就爱情而言,女人是专业的,男人是业余的. 3.快乐使 ...

  6. 磨刀-CodeWarrior11生成的Makefile解析

    https://mp.weixin.qq.com/s/plvviDFLsLQeg9ZeP_3WMA   一. 简介 Code Warrior 11是基于Eclipse CDT开发的集成开发环境(IDE ...

  7. Rocket - diplomacy - 模块结构信息

    https://mp.weixin.qq.com/s/cTRxXwWNEeb4-XX_t4bRcg   讨论模块结构信息的来源及使用方式.     ​​   1. diplomacy   diplom ...

  8. 文件包含漏洞(file inclusion)

    文件包含漏洞原理:(php) 是指当服务器开启allow_url_include选项的时候,通过php某些特性函数.如include().include_once().require().requir ...

  9. Linux (八)服务

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 1.服务的概念 操作系统中在后台持续运行的程序,本身并没有操作界面,需要通过端口号访问和操作.CentO ...

  10. Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数

    问题描述 不超过19000的正整数中,与19000互质的数的个数是多少? 答案提交 这是一道结果填空的题,你只需要算出结果后提交即可.本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将 ...