Java并发--happens-before详解

Java并发编程核心:Happens-Before原则八大规则详解与实战 在并发编程中,内存可见性和指令重排序是导致多线程数据不一致的核心挑战。Java内存模型(JMM)通过定义一套Happens-Before规则,为开发者提供了跨平台的内存一致性保证。这些规则从底层原理上规范了volatile、synchronized等关键字的语义,确保一个线程的写操作对另一个线程可见。理解Happens-Before原则是编写正确、高效并发程序的基础,它不仅是避免数据竞争和状态混乱的理论依据,更是工程实践中实现线程安全计数器、安全发布对象等场景的关键。通过剖析程序次序、管程锁定、volati 阅读详情

happens-before的定义

JSR-133使用happens-before的概念来指定两个操作之间的执行顺序。由于这两个操作可以在一个线程之内,也可以是在不同线程之间。因此,JMM可以通过happens-before关系向程序员提供跨线程的内存可见性保证(如果A线程的写操作a与B线程的读操作b之间存在happensbefore关系,尽管a操作和b操作在不同的线程中执行,但JMM向程序员保证a操作将对b操作可见)。

《JSR-133:Java Memory Model and Thread Specification》对happens-before关系的定义如下

  1. 如果一个操作happens-before另一个操作,那么第一个操作的执行结果将对第二个操作可见,而且第一个操作的执行顺序排在第二个操作之前。
  2. 两个操作之间存在happens-before关系,并不意味着Java平台的具体实现必须要按照happens-before关系指定的顺序来执行。如果重排序之后的执行结果,与按happens-before关系来执行的结果一致,那么这种重排序并不非法(也就是说,JMM允许这种重排序)。

上面的1)是JMM对程序员的承诺。 从程序员的角度来说,可以这样理解happens-before关系:如果A happens-before B,那么Java内存模型将向程序员保证——A操作的结果将对B可见,且A的执行顺序排在B之前。注意,这只是Java内存模型向程序员做出的保证!

上面的2)是JMM对编译器和处理器重排序的约束原则。 正如前面所言,JMM其实是在遵循一个基本原则:只要不改变程序的执行结果(指的是单线程程序和正确同步的多线程程序)编译器和处理器怎么优化都行。JMM这么做的原因是:程序员对于这两个操作是否真的被重排序并不关心,程序员关心的是程序执行时的语义不能被改变(即执行结果不能被改变)。因此,happens-before关系本质上和as-if-serial语义是一回事。

happens-before规则

《JSR-133:Java Memory Model and Thread Specification》定义了如下happens-before规则

  1. 程序顺序规则: 一个线程中的每个操作,happens-before于该线程中的任意后续操作。
  2. 监视器锁规则: 对一个锁的解锁,happens-before于随后对这个锁的加锁。
  3. volatile变量规则: 对一个volatile域的写,happens-before于任意后续对这个volatile域的读。
  4. 传递性: 如果A happens-before B,且B happens-before C,那么A happens-before C。
  5. start()规则: 如果线程A执行操作ThreadB.start()(启动线程B),那么A线程的ThreadB.start()操作happens-before于线程B中的任意操作。
  6. join()规则: 如果线程A执行操作ThreadB.join()并成功返回,那么线程B中的任意操作happens-before于线程A从ThreadB.join()操作成功返回。

示例:volatile写-读建立的happens-before关系图
在这里插入图片描述
从图中可以看出1 happens-before 2和3 happens-before 4由程序顺序规则产生。由于编译器和处理器都要遵守as-if-serial语义,也就是说,as-if-serial语义保证了程序顺序规则。因此,可以把程序顺序规则看成是对as-if-serial语义的“封装”。

2 happens-before 3是由volatile规则产生。前面提到过,对一个volatile变量的读,总是能看
到(任意线程)之前对这个volatile变量最后的写入。因此,volatile的这个特性可以保证实现
volatile规则。

1 happens-before 4是由传递性规则产生的。这里的传递性是由volatile的内存屏障插入策略和volatile的编译器重排序规则共同来保证的。

示例:start()规则
假设线程A在执行的过程中,通过执行ThreadB.start()来启动线程B;同时,假设线程A在执行ThreadB.start()之前修改了一些共享变量,线程B在开始执行后会读这些共享变量。下图是该程序对应的happens-before关系图。

在这里插入图片描述
1 happens-before 2由程序顺序规则产生。2 happens-before 4由start()规则产生。根据传递性,将有1 happens-before 4。这实意味着,线程A在执行ThreadB.start()之前对共享变量所做的修改,接下来在线程B开始执行后都将确保对线程B可见。

示例:join()规则
假设线程A在执行的过程中,通过执行ThreadB.join()来等待线程B终止;同时,假设线程B在终止之前修改了一些共享变量,线程A从ThreadB.join()返回后会读这些共享变量。下图是该程序对应的happens-before关系图。
在这里插入图片描述

2 happens-before 4由join()规则产生;4 happens-before 5由程序顺序规则产生。根据传递性规则,将有2 happens-before 5。这意味着,线程A执行操作ThreadB.join()并成功返回后,线程B中的任意操作都将对线程A可见。

Java并发 Java内存模型 happens-before原则 1. 两个关键问题 并发编程中,需要处理两个关键问题:线程之间如何通信 和 线程之间如何同步。 通信是指线程之间怎样交换信息。同步是指怎样控制不同线程间操作发生的相对顺序。 在命令式编程中,线程之间的通信机制有两种:共享内存 和 消息传递。 在共享内存的并发模型里,线程之间共享程序的公共状态,通过写-读内存中的公共状态进行隐式通信;并且它的同步也是显示进行的,必须显示指定某段代码需要在线程之间互斥... 阅读详情

相关推荐

深信服技术认证“SCCA-C”划重点:信服云托管云

该认证包括云数据中心基础、云计算基础、云计算关键技术、云计算交付和运维体系、云计算技术商业应用、信服云托管云、深信服超融合HCI、深信服桌面云aDesk、深信服分布式存储EDS、深信服应用交付AD。学习并获得SCCA-C认证后,可以具备深信服产品功能原理与实践,能够根据业务需求,协助完成云产品方案落地与实施;能够根据业务需求,完成深信服云产品的部署和管理的基本工作。为帮助大家更加系统化地学习云计算知识,高效通过云计算工程师认证,深信服特推出“SCCA-C认证备考秘笈”,共十期内容。

sangfor_edu的博客 614

Java内存模型之happens-before

导读 happens-before是JMM最核心的概念。对应Java程序员来说,理解happens-before是理解JMM(Java内存模型)的关键 一.happens-before的简介 由于存在线程本地内存和主内存的原因,再加上重排序,会导致多线程环境下存在可见性的问题。那么我们正确使用同步、锁的情况下,线程A修改了变量a何时对线程B可见? 我们无法就所有场景来规定某个线程修改的变量何...

麦叔 591

可视化工具--Plotly

随着信息技术的发展和硬件设备成本的降低,当今的互联网存在海量的数据,要想快速从这些数据中获取更多有效的信息,数据可视化是重要的一环。对于Python语言来说,比较传统的数据可视化模块是Matplotlib,但它存在不够美观、静态性、不易分享等缺点,限制了Python在数据可视化方面的发展。   为了解决这个问题,新型的动态可视化开源模块Plotly应运而生。由于Plotly具有动态、美观、易用、种类丰富等特性,所以一经问世就受到开发人员的喜爱。

YFater的博客 1万+

happens-before规则——理解happens-before规则

happens-before 是 JMM 最核心的概念。对应 Java 程序员来说,理解 happens-before是理解 JMM 的关键。从 JDK 5 开始,Java 使用新的 JSR-133 内存模型(除非特别说明,本文针对的都是JSR-133 内存模型)。JSR-133 使用 happens-before 的概念来阐述操作之间的内存可见性。在 JMM 中,如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必 须要存在 happens-before 关系。...

秃了也弱了 2035

深入浅出一文搞懂Raft协议

前言 在分布式的世界里,要说最核心最复杂的功能,一致性的实现无出其右,之前的paxos算法堪称经典,被认为是同类算法中效果最好的,基本上成为分布式一致性的代名词,但是paxos算法也是出了名的难理解,而且相当不好实现。本人也花了很多时间、看了很多材料也没有真正理解。所以基于paxos的思想进行的一致性算法的简化和实现就成为了现实的需求,在此背景下,本文的主角Raft就出现了。 Raft算法的头号目标就是容易理解(UnderStandable),这从论文中就可以看出来。当然,R...

microGP的专栏 6486

告别Win11睡眠假死:深入解析Modern Standby S0与S3冲突及注册表修复方案

本文深入解析了Windows 11中Modern Standby(S0)与传统睡眠(S3)模式的冲突,该冲突是导致电脑睡眠后出现假死、断网等问题的根源。文章提供了通过修改注册表键值(PlatformAoAcOverride)强制启用稳定S3睡眠的终极修复方案,并附有详细诊断步骤与避坑指南,帮助用户彻底解决睡眠故障。

ol789012的博客 823

Happens-Before原则的通俗理解

指令重排&happens-before 原则 & 内存屏障:https://www.cnblogs.com/ITPower/p/13580691.html Java内存模型:https://www.cnblogs.com/yuanfy008/p/9252555.html

pscool的博客 2667

Linux命令行入门:从零掌握服务器运维与Shell脚本基础

在信息化时代,操作系统是数字世界的基石,而终端命令行则是高效驾驭服务器的核心技能。无论是软件部署、服务监控还是故障排查,掌握基于Shell的指令操作都能大幅提升工程效率。从最基础的文件目录管理、文本处理,到权限控制、进程监控与网络调试,命令行提供了一套强大且可自动化的操作范式。尤其对于运维工程师和开发者而言,理解管道、重定向以及脚本化任务,意味着将重复劳动转化为可复用的自动化流程。本文从环境准备讲起,系统梳理常用Linux命令的实际场景与输出验证,并延伸至Shell脚本编写与定时任务,帮助初学者快速建立从操

weixin_30522983的博客 257

happen-before原则

happen-before是JMM最核心的概念,所以在了解happen-before原则之前,首先需要了解java的内存模型。 JMM内存模型      java内存模型是共享内存的并发模型,线程之间主要通过读-写共享变量来完成隐式通信。java中的共享变量是存储在内存中的,多个线程由其工作内存,其工作方式是将共享内存中的变量拿出来放在工作内存,操作完成后,...

怪咖小青年的博客 3万+

信息收集-服务器信息

服务器上面可以运行大量的系统服务和第三方应用服务,如果操作系统或者第三方软件没有及时升级打补丁,攻击者就有可能直接通过服务器上运行的服务进行攻击。

weixin_49349476的博客 1446

SAP 消息号T-CODE

SAP消息号修改汇总 确实有很多消息是可以修改的 FI: oBA5|oFMG|oFPM MM: oMRM|oKZZ|oMT4|oMCQ|o04C| SD: oVAH(V4)|oVM1(VL) CO:  oPR4_ACT|oPR4_CK|oPR4_CKML|oPR4_CKPF|oPR4_KKA|oPR4_KKP|oPR4_KKS| oPR4_KKS1|oPR4_P

heng0757的专栏 1万+

Java并发编程的暗号:Happens-Before原则详解

Happens-Before原则是Java并发编程的基石,它通过八条核心规则为多线程环境下的内存可见性和有序性提供了重要保证。编写正确的并发代码,避免内存可见性问题理解并发工具的原理,如synchronized、volatile、并发集合等进行有效的并发调试,快速定位和解决并发问题设计高性能的并发架构,在保证正确性的前提下提升性能记住,在并发编程的世界里,Happens-Before原则就像交通规则一样重要:虽然遵守规则不一定能保证绝对安全,但不遵守规则几乎肯定会出问题!

热爱技术、喜欢学习、乐于分享 726

基于Simulink的间接功率控制的矩阵变换器

通过上述步骤,我们成功设计并实现了基于 Simulink 的间接功率控制的矩阵变换器仿真模型。该模型能够通过控制输入电流和输出电压,实现对功率的间接控制,适用于电机驱动、可再生能源系统、电力传输等领域。通过虚拟场景仿真、参数优化和性能评估,验证了系统的稳定性和高效性,并通过调整 PI 控制器参数和优化调制算法,进一步提升了系统的性能。

MHD0815的博客 296

Java并发理论(二):as-if-serial规则和happens-before规则详解

引言 我们知道为了提高并行度,优化程序性能,编译器和处理器会对代码进行指令重排序。指令重排序可参看指令重排序和数据依赖性详解。但为了不改变程序的执行结果,尽可能地提高程序执行的并行度,我们需要了解as-if-serial规则和happens-before规则。 as-if-serial规则 as-if-serial语义的意思指:不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不能被改变。编译器、runtime和处理器都必须遵守as-if-serial语义。 为了遵守as-if-ser

少侠露飞的学习笔记 3626

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

深入解析Java并发编程中的内存可见性与happens-before原则

A对共享变量的修改对B可见A的执行顺序排在B之前理解Java内存模型和happens-before原则是编写正确并发程序的基础。清楚每个同步操作建立的内存可见性保证了解不同并发构造的内存语义优先使用线程安全的集合和工具类对共享数据的访问保持警惕随着Java版本的演进,新的并发特性如VarHandle和Memory Order模式提供了更细粒度的内存控制,但happens-before原则仍然是理解Java并发编程的基石。

hi星尘的博客 791

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Happens-Before 规则

摘要:Happens-Before规则是Java内存模型(JMM)的核心概念,定义了多线程环境下操作间的可见性契约。它解决了并发中的可见性和有序性问题,为开发者提供了可推理的并发模型。六大规则包括程序顺序规则、volatile变量规则、传递性、监视器锁规则、线程启动规则和线程终止规则,分别应用于单线程顺序执行、volatile变量同步、可见性链构建、synchronized块同步、线程初始化数据传递和线程结果获取等场景。这些规则确保即使存在编译器/CPU重排序,程序的逻辑正确性仍能得到保障。

阿常的博客 362

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

JMM底层之happnes-before原则

其实就是Java内存模型中定义的两项操作之间的排序关系,如果操作A happens-before操作B,就是在说发生在B之前的操作A产生的影响能被B观察到。下面的例子简单的说明如果存在先行关系,就不用担心指令重排对两个线程的影响,不存在先行关系就要特别小心了:以下操作在线程A中执行i=1;以下操作在线程B中执行j=i;以下操作在线程C中执行i=2;1 是根据happnes-before原则,“i=1” 的结果可以被观察到;

沛哥儿的专栏 966

JAVA并发二,深入理解并发

创建一个名为。

m0_46271812的博客 1620

java并发编程分析总结

总的来说,java并发编程要掌握的大概为一下几个方面: java内存模型 java中的锁 java并发容器 java并发工具类 java Executor框架 本人最近也在学习中,所以会不时更新上面五个方面的学习总结,废话不多说,这就开干。 1.java内存模型 这一块需要掌握几个点: java内存特性 volatile关键字 happens-before规则 既然讲到内存...

wolflikeinnocence的博客 239

Java 内存模型详解:volatile、synchronized 与 happens-before

本文从可见性、原子性与有序性出发,系统讲解 Java 内存模型(JMM)的核心原理,深入分析 `volatile`、`synchronized` 及 happens-before 规则。结合状态通知、双重检查锁、安全发布、原子类和 VarHandle 等案例,说明不同同步机制的适用场景、常见误区与线程安全代码的设计方法。

qq_29029209的博客 357

Java并发编程核心挑战与高并发实战解决方案

并发编程是现代服务端开发的核心技术,其核心挑战在于处理多线程环境下的原子性、可见性和有序性问题。Java内存模型(JMM)通过happens-before原则和内存屏障机制,为开发者提供了解决这些问题的理论基础。在实际工程中,合理使用synchronized、volatile和Atomic类族等并发工具,可以显著提升系统性能。高并发场景下,线程池配置、锁优化和并发容器的选择尤为关键,例如使用ConcurrentHashMap处理高频更新,或通过锁分离技术提升读写性能。这些技术在电商秒杀、金融支付等高并发系统

weixin_34218579的博客 379

Java并发编程(总目录)

一.Java内存模型Java内存模型的抽象结构Java内存模型之happens-before二.Java并发编程基础Java多线程的概念和原理Java多线程的创建和启动线程的生命周期详解Thread类相关的API介绍如何安全的终止线程三.Java中的锁Java中各种锁的详解Java中的锁之Lock接口Java中的锁之重入锁:ReentrantLock四.Java并发容器和框架为什么要使用Concu...

yingjian2215的博客 123

【并发编程】一文带你读懂深入理解Java内存模型(面试版本)

并发编程这一块内容,是高级资深工程师必备知识点,25K起如果不懂并发编程,那基本到顶。但是并发编程内容庞杂,如何系统学习?本专题将会系统讲解并发编程的所有知识点,包括但不限于: 线程通信机制,深入JMM内存模型原理,深入synchronized原理,深入volatile原理,DCL,详解AQS,CAS,可重入锁,读写锁原理,详解并发工具类,深入理解threadLocal,Fork、Join,原子...

284

JAVA并发编程 概念篇 【持续更新】

Java并发编程 感悟 1.技术在解决一个问题的同时,必然会带来另外一个问题 概念解析 1.可见性 一个线程对共享变量的修改,另外一个线程能够立刻看到,我们称为可见性 2.原子性 我们把一个或者多个操作在CPU执行的过程中不被中断的特性称为原子性。 备注:CPU能保证的原子操作是CPU指令级别的,而不是高级语言的操作符。 例如:count += 1,至少需要三条CPU...

w1170384758的博客 259

Java并发编程-理论基础

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

weixin_50701238的博客 872
上一篇: Java并发--concurrent包的实现
下一篇: ActiveMQ--概述
吴声子夜歌
博客等级 码龄9年 2688粉丝 2271原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值