当前位置: 首页 > news >正文

JMM之先行发生原则(happens-before)详解

1、概述

在JMM规范下,如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须存在happers-before(先行发生)原则。

例如

int x = 10 ;

int y = x;

这两行代码中第二个操作 y=x ,因为需要将x值赋值给y,所以第一行代码的结果需要对第二行代码可见。也就是第一行代码happers-before第二行代码。

有些朋友看了可能觉得,作者说的不是废话嘛,这两行代码肯定是先执行第一行再执行第二行。答案肯定是的,因为y的值依赖x的值,这属于JMM规范happens-before原则内的,所以会按照代码编写顺序执行。假如没有happens-before原则,则y的值可能就不会等于10,可见happens-before原则的重要性。

happens-before原则是判断数据是否存在竞争,线程是否安全的非常有用的手段。依赖这个原则,我们可以通过几条简单的规则,解决并发环境下两个操作之间是否可能存在冲突的所有问题,而不需要陷入Java内存模型苦涩难懂的底层编译原理之中。

那接下来我们就说说happens-before都有那些具体原则。

2、happens-before具体原则

  • 次序规则

一个线程内,按照代码顺序,写在前面的操作先行发生于写在后面的操作。

注意:这里是一个线程内,如果是多个线程这不属于happens-before原则

int x = 10;

int y = 20;

在一个线程内 在执行y=20 时,x肯定是10;但是如果在多线程下由于编译器优化,指令重排序 在执行y=20时,x可能等于0

  • 锁定规则

一个unlock操作先行发生于后面(这里的”后面“是指时间上的先后)对同一把锁的lock操作;

    static Lock lock = new ReentrantLock();public static void main(String[] args) {lock.lock();try {System.out.println("------锁定1");} finally {//解锁lock.unlock();}//再次锁定  第二次加锁操作肯定是发生在上一次解锁 之后lock.lock();try {System.out.println("------锁定2");} finally {lock.unlock();}}
  • volatile变量规则

对一个volatile变量的写操作先行发生于后面对这个变量的读操作,前面的写对后面的读是可见的,这里的”后面“也是指时间上的先后。

咱们都知道被volatile修饰的变量,拥有JMM三大特性的可见性和有序性。对于同一个共享volatile变量,线程A修改了变量值,则其他线程立马就可以看到。

static volatile Boolean flag = false;public static void main(String[] args) {new Thread(() -> {if (!flag) {System.out.println("--正常运行");}System.out.println("--终止");}, "t1").start();new Thread(() -> {//更改volatile 变量值,t1线程立马就能收到flag = true;System.out.println("终止线程t1");}, "t2").start();}

看到这里是不是就知道了,为啥 volatile 修饰变量,变量具有可见性和有序性,其实底层是happens-before原则制定的。

  • 传递性规则

如果操作A先行发生于操作B,操作B先行发生于操作C,那么操作A肯定先行发生于C。

  • 线程启动规则

Thread对象的start()方法先行发生于此线程中执行的所有代码。

public static void main(String[] args) {Thread t1 = new Thread(() -> {/*** 线程内操作 后执行*/System.out.println("线程执行内容1");System.out.println("线程执行内容2");}, "t1");// start()方法先执行t1.start();}
  • 线程中断规则

对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生,可以通过Thread.interrupted()或者isInterrupted()检测到是否有中断发生。

Thread t1 = new Thread(() -> {//检查线程中断标识位是否被设置为truewhile (!Thread.currentThread().isInterrupted()) {System.out.println("---正常执行");}System.out.println("被中断");}, "t1");//线程1启动t1.start();new Thread(() -> {System.out.println("将t1 线程中断标识位设置为true");t1.interrupt();}, "t2").start();

---正常执行
.....
.....
---正常执行
---正常执行
---正常执行
---正常执行
将t1 线程中断标识位设置为true
---正常执行
被中断 

  • 线程终止规则

线程中的所有操作都先行发生于对此线程的终止检测,可以通过Thread.join()方法结束、Thread.isAlive()的返回值等手段检测到线程已经终止执行。

  • 对象终结规则

一个对象的初始化完成(构造函数执行结束)先行发生于它的finalize()方法的开始。

这条规则指出,一个对象在被垃圾回收之前必须已经进过初始化,垃圾回收不可能也不能去回收一个根本不存在的对象。

3、总结

如果一个操作happens-before另一个操作,那么第一个操作的执行结果将对第二个操作可见,而且第一个操作的执行顺序排在第二个操作之前。

两个操作之间存在happens-before关系,并不意味着一定要按照happens-before原则制定的顺序来执行。如果重排序之后的执行结果与按照happens-before关系来执行的结果一致,那么这种重排序是可以正常执行的。

相关文章:

JMM之先行发生原则(happens-before)详解

1、概述 在JMM规范下,如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须存在happers-before(先行发生)原则。 例如 int x 10 ; int y x; 这两行代码中第二个操作 yx ,因为需要将x值赋值给y,所以第一行代码的…...

含分布式电源的配电网可靠性评估研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

安全加固服务是什么?哪些行业需要做?

安全加固服务是什么?安全加固服务是一种针对企业信息系统、网络设备、应用程序等进行安全加固和优化的服务。安全加固服务的主要目的是保障企业信息系统的安全性和稳定性,有效防范各类网络攻击和安全威胁。 安全加固服务是什么?通常包括以下…...

好程序员:Java书籍推荐,程序员必看的5本Java书籍,赶紧收藏!

今天好程序员给大家推荐5本Java书籍,各大高校都在使用(具体名单如下),所有学习Java的程序员都不应该错过! 第一本Java书籍《Java EE(SSM框架)企业应用实战》 本书全面介绍了JavaEE中MyBatis、Sp…...

maven将jar包添加到本地仓库

第一步:下载需要添加的jar包 可以在maven库中查找下载,也可以在对应官网下载 maven库网址:https://mvnrepository.com/ 找到对应版本的jar包下载 第二步:将下载的jar包放到指定位置(位置自己指定)&#xf…...

4.12--计算机网络之TCP篇之TCP 协议的缺陷+如何基于 UDP 协议实现可靠传输?--(复习+大总结)---沉下心来(加油呀)

TCP 协议四个方面的缺陷: 1.升级 TCP 的工作很困难; TCP 协议是在内核中实现的,应用程序只能使用不能修改,如果要想升级 TCP 协议,那么只能升级内核。 而升级内核这个工作是很麻烦的事情 2.TCP 建立连接的延迟&#x…...

数据库网络编程

数据库网络编程是一个重要的领域,它涉及到如何使用编程语言与数据库进行交互,以及如何设计和实现网络应用程序。在这篇文章中,我将探讨数据库网络编程的基础知识、常用技术和实践经验,以及一些应用案例和未来发展趋势。 一、基础…...

为什么现代企业都在使用ERP系统 它有哪些优势

随着科技的不断发展,企业管理方式也在不断地发生改变。在这个信息化的时代,企业要想取得成功,必须要善于利用先进的信息化技术工具。其中,ERP系统是企业管理中不可或缺的重要工具。本文将探讨现代企业为什么会使用ERP系统&#xf…...

别再用 BeanUtils 了,这款 PO VO DTO 转换神器不香么?

老铁们是不是经常为写一些实体转换的原始代码感到头疼,尤其是实体字段特别多的时候。介绍一个开源项目 mapstruct ,可以轻松优雅的进行转换,简化你的代码。当然有的人喜欢写get set,或者用BeanUtils 进行复制,代码只是…...

LeetCode算法小抄-- 最近公共祖先 和 完全二叉树的节点个数

LeetCode算法小抄-- 最近公共祖先 和 完全二叉树的节点个数 最近公共祖先[236. 二叉树的最近公共祖先](https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/)[235. 二叉搜索树的最近公共祖先](https://leetcode.cn/problems/lowest-common-ancestor-of-a-b…...

php、redis实现分布式锁的正确写法(原子操作 通用类 加讲解)

最终代码(通用类) 1 面试中、实际工作中&#xff0c;经常涉及到 redis 分布式锁&#xff0c;正确写法如下。先奉上代码&#xff0c;再讲解。 <?php namespace app\common\library; /*** 通用分布式锁(原子操作)*/ class Lock {/*** 获取redis实例* return \Redis* throws…...

Transformer在时序预测的应⽤第一弹——Autoformer

Transformer在时序预测的应⽤第一弹——Autoformer 原文地址&#xff1a;Autoformer: Decomposition Transformers with Auto-Correlation for Long-Term Series Forecasting&#xff08;NIPS 2021&#xff09; 做长时间序列的预测 Decomposition把时间序列做拆分&#xff0c…...

文章改写神器在线-AI续写文章生成器

AI续写生成器 AI续写生成器是一种利用人工智能技术的创意工具&#xff0c;能够提高写作效率&#xff0c;为营销推广带来全新的可能性。无论你是写手、广告人员还是市场营销人员&#xff0c;这个工具都能够有效地解决你在写作中遇到的难题。 在内容创作行业中&#xff0c;原创…...

一秒钟给硬盘文件做个树状结构目录

一秒钟给硬盘文件做个树状结构目录 一、背景 对于长时间坐在电脑前的打工人来说&#xff0c;若没有养成良好文件分类习惯的话&#xff0c;年终整理电脑文件绝对是件头疼的事情。 给磁盘文件做个目录&#xff0c;一目了然文件都在哪里&#xff1f;想想都是件头疼的事情。 对于…...

电脑重装系统后会怎样?

​有小伙伴的电脑系统运行缓慢卡顿&#xff0c;现在想通过重装系统来解决问题。咨询电脑重装系统会怎么样对系统有影响吗&#xff0c;现在小编就带大家看看电脑重装系统后会怎样。 方法/步骤&#xff1a; 一、电脑重装系统会怎么样 1、我们的电脑重装系统后&#xff0c;电脑…...

100种思维模型之反熵增思维模型-47

查理芒格被誉为反熵增思维模型的倡导者。本文将介绍查理芒格的反熵增思维模型&#xff0c;并分析它的实用性。 一、什么是熵增&#xff1f; 在物理学中&#xff0c;熵是衡量系统无序程度的指标。系统的熵越高&#xff0c;其无序程度越高。这个概念也可以应用到其他领域。在金融…...

【网络安全】Xss漏洞

xss漏洞 xss漏洞介绍危害防御方法xss测试语句xss攻击语句1. 反射性xss2.存储型xss3.DOM型xssdvwa靶场各等级渗透方法xss反射型&#xff08;存储型方法一致&#xff09;LowMediumHightimpossible Dom型LowMediumHight xss漏洞介绍 定义&#xff1a;XSS 攻击全称跨站脚本攻击&am…...

17.网络爬虫—Scrapy入门与实战

这里写目录标题 Scrapy基础Scrapy运行流程原理Scrapy的工作流程Scrapy的优点 Scrapy基本使用(豆瓣网为例)创建项目创建爬虫配置爬虫运行爬虫如何用python执行cmd命令数据解析打包数据打开管道pipeline使用注意点 后记 前言&#xff1a; &#x1f3d8;️&#x1f3d8;️个人简介…...

【面试题】JavaScript 中 try...catch 的使用技巧 ?

大厂面试题分享 面试题库 前后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 web前端面试题库 VS java后端面试题库大全 作为一位 Web 前端工程师&#xff0c;JavaScript 中的 try...catch 是我们常用的特性之一。…...

Java 命名格式规范

Java 命名格式规范 概述 简洁清爽的代码风格应该是大多数开发工程师所期待的。在编码过程中笔者常常因为起名字而纠结&#xff0c;夸张点可以说是编程 5 分钟&#xff0c;命名两小时&#xff01;究竟为什么命名成为了编码中的拦路虎。 每个公司都有不同的标准&#xff0c;目…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案

目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后&#xff0c;迭代器会失效&#xff0c;因为顺序迭代器在内存中是连续存储的&#xff0c;元素删除后&#xff0c;后续元素会前移。 但一些场景中&#xff0c;我们又需要在执行删除操作…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)

一、OpenBCI_GUI 项目概述 &#xff08;一&#xff09;项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台&#xff0c;其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言&#xff0c;首次接触 OpenBCI 设备时&#xff0c;往…...