Java的先行发生原则

这篇具有很好参考价值的文章主要介绍了Java的先行发生原则。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

先行发生原则(Happens-Before)是Java内存模型定义的一个等效判断原则。依赖这个原则,我们可以通过几条简单规则判断数据是否存在竞争,线程是否安全,而不需要陷入Java内存模型苦涩难懂的定义之中。


“先行发生”原则指的是什么。比如说操作 A 先行发生于操作 B,其实就是说在操作 B 发生之前,操作 A 产生的影响能被操作 B 观察到,“影响”包括修改了内存中共享变量的值、发送了消息、调用了方法等。

下面是Java内存模型下一些“天然的”先行发生关系,这些先行发生关系无须任何同步器协助就已经存在,可以在编码中直接使用。如果两个操作之间的关系不在此列,并且无法从下列规则推导出来,则这两个操作就没有顺序性保障,虚拟机可以对它们进行重排序。

  • 程序次序规则(Program Order Rule):在一个线程内,按照控制流顺序,书写在前面的操作先行发生于书写在后面的操作。注意,这里说的是控制流顺序而不是程序代码顺序,因为要考虑分支、循环等结构。
  • 管程锁定规则(Monitor Lock Rule):一个 unlock 操作先行发生于后面对同一个锁的 lock 操作。 这里必须强调的是“同一个锁”,而“后面”是指时间上的先后。
  • volatile 变量规则(Volatile Variable Rule):一个对 volatile 变量的写操作先行发生于后面对这个 volatile 变量的读操作,这里的“后面”同样是指时间上的先后。
  • 线程启动规则(Thread Start Rule):Thread 对象的 start() 方法先行发生于此线程的每一个动作。
  • 线程终止规则(Thread Termination Rule):线程中的所有操作都先行发生于对此线程的终止检测。我们可以通过 Thread::join() 方法是否结束、Thread::isAlive() 的返回值等手段检测线程是否已经终止执行,这就算是对此线程的终止检测。
  • 线程中断规则(Thread Interruption Rule):Thread 对象的 interrupt() 方法先行发生于被中断线程的中断检测。我们可以通过 Thread::interrupted() 方法检测到是否有中断发生,这就算是被中断线程的中断检测。
  • 对象终结规则(Finalizer Rule):一个对象的初始化完成(构造函数执行结束) 先行发生于它的 finalize() 方法的开始。
  • 传递性(Transitivity):如果操作 A 先行发生于操作 B,操作 B 先行发生于操作 C,那就可以得出结论:操作 A 先行发生于操作 C。

Java 语言无须任何同步手段保障就能成立的先行发生规则有且只有上面这些。


“时间上的先后顺序”与“先行发生”之间有什么不同?

  • 一个操作“时间上的先发生”不代表这个操作会是 “先行发生”。譬如:操作 A 是 ,线程 A 对未被 volatile 修饰的共享变量的写操作;操作 B 是,线程 B 对该共享变量的读操作。在时间上,操作 A 比操作 B 先发生,但是不代表操作 A 先行发生于操作 B。
  • 如果一个操作“先行发生”,也不能推导出这个操作必定是“时间上的先发生”。譬如:程序次序规则,在一个线程内,按照控制流顺序,书写在前面的操作 A 先行发生于书写在后面的操作 B。但是,不代表在时间上,操作 A 比操作 B 先发生。普通的变量会保证在方法的执行过程中,所有依赖赋值结果的地方都能获取到正确的结果,而不能保证变量赋值操作的顺序与程序代码中的执行顺序一致。

时间先后顺序与先行发生原则之间基本没有因果关系,所以我们衡量并发安全问题的时候不要受时间顺序的干扰,一切必须以先行发生原则为准。

参考资料

《深入理解Java虚拟机》第 12 章:Java 内存模型与线程 12.3 Java 内存模型

02 | Java内存模型:看Java如何解决可见性和有序性问题 (geekbang.org)文章来源地址https://www.toymoban.com/news/detail-471759.html

到了这里,关于Java的先行发生原则的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【已解决】RuntimeError Java gateway process exited before sending its port number

    🎯方法一 在代码前加入如下代码(如图): import os os.environ[‘JAVA_HOME’] = “/usr/local/jdk1.8.0_221” # 记得把地址改成自己的 🎯方法二 目光锁定pycharm标题栏(最上方),找到Run—— Edit Configurations——Environment variables 按图中所示,添加jdk路径(不用添加其他的路径了,一个就

    2024年02月07日
    浏览(43)
  • (已解决)RuntimeError: Java gateway process exited before sending its port number

    今天用Pycharm远程使用pysaprk解释器时,跑代码出现了这个错误: RuntimeError: Java gateway process exited before sending its port number 找了好多博客都没解决问题,有说重装spark的,有说本地配Java_home的,后面我自己发现是linux上有个文件忘记配了 如图:在根目录 打开.barshc 然后在文件的最

    2024年02月16日
    浏览(39)
  • 在pycharm中使用PySpark 出现Java gateway process exited before sending its port number.

    # 原因是没有下载Java(jdk) 程序出现下面错误: 解决办法: 1、 2、 3、先点击“+”  ,添加这一行,点击确定即可。再次之前先判断你电脑上没有jdk,有的话,直接添加,也可以手动添加。如果没有,则下载jdk,第五步,告诉你如何下载。 4、首先判断电脑上是否有jdk;   在

    2024年04月09日
    浏览(47)
  • 鸿蒙开发ArkTS通过Time.before及after方法判断两个时间的先后(类似于java的Time类)

    本文使用ArkTS实现了类似于java的Time类的功能方法。 OpenHarmony或者HarmonyOS的 ArkTS 是否有类似于java的Time类,可以通过Time.before及after方法判断两个时间的先后 ? 可以实现此功能 类似于下面的代码:

    2024年02月04日
    浏览(37)
  • 从Java 1.8到Java 21,发生了很多变化和改进

    从Java 1.8到Java 21,发生了很多变化和改进。以下是一些主要的变化和需要注意的事项: 模块化系统 (JEP 261) : 在Java 9中引入,这改变了Java的打包和部署方式。 使用 module-info.java 来定义模块和其依赖。 接口中的私有方法 (JEP 185) : 从Java 9开始,接口中可以定义私有方法。 局部变

    2024年04月17日
    浏览(35)
  • 设计模式之7大设计原则-Java版

    软件设计模式是前辈们代码设计经验的总结,可以反复使用。设计模式共分为3大类,创建者模式(5种)、结构型模式(7种)、行为型模式(11种),一共23种设计模式,软件设计一般需要满足7大基本原则。下面通过5章的学习一起来看看设计模式的魅力吧。 目录 1.1、设计模式概述

    2024年01月20日
    浏览(39)
  • 测试先行:探索测试驱动开发的深层价值

    在软件开发的世界中,如何确保代码的质量和可维护性始终是一个核心议题。测试驱动开发(TDD)为此提供了一个答案。与传统的开发方法相比,TDD鼓励开发者从用户的角度出发,先定义期望的结果,再进行实际的开发。这种方法不仅可以确保代码满足预期的需求,还可以在

    2024年02月11日
    浏览(34)
  • 健启星|医学营养的市场先行者

    随着《“健康中国2030”规划纲要》、《国民营养计划(2017-2030年)》等政策的陆续发布,标志着以传统药物治疗为中心的医疗模式时代正式转型到以预防和康复为中心的新的医学营养时代。在此背景下,符合时代需求的特医食品成为“医学营养”发展方向。 特医食品成医学

    2024年02月13日
    浏览(67)
  • 前端先行模拟接口(mock+expres+json)

    目录 mock模拟数据:data/static.js 路由:index.js 服务器:server.js yarn /node 启动服务器:yarn start 客户端:修改代理路径(修改设置后都要重启才生效) 示例 后端框架express构建服务器 前端发起请求 JSON 静态数据:res.status === 304 3xx - Redirection(重定向):附加操作已完成请求 301 Mov

    2024年02月13日
    浏览(40)
  • Python搭建PySpark执行环境入口时出现RuntimeError: Java gateway process exited before sending its port number解决办法

    (3条消息) pyspark Exception: Java gateway process exited before sending its port number(2021年10月29日版)_明天,今天,此时的博客-CSDN博客 (3条消息) 测试pyspark时,解决Java gateway process exited的问题_コキリ的博客-CSDN博客 python - Pyspark: Exception: Java gateway process exited before sending the driver its port numbe

    2024年02月11日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包