0

0

在Java中happens-before规则如何保证有序性_Java并发一致性说明

P粉602998670

P粉602998670

发布时间:2026-02-09 05:33:12

|

631人浏览过

|

来源于php中文网

原创

happens-before 是定义操作间可见性与顺序约束的偏序关系规则,而非强制执行排序;JVM/CPU 可在不破坏其规则前提下自由重排。

在java中happens-before规则如何保证有序性_java并发一致性说明

happens-before 不能直接“保证有序性”,它定义的是可见性与动作顺序的约束关系

很多人误以为 happens-before 是 JVM 对代码执行顺序的强制排序指令,其实它是一组**偏序关系规则**,用于判断一个操作的结果对另一个操作是否可见、是否可被重排。JVM 和 CPU 可以在不破坏任何 happens-before 关系的前提下自由重排序——这才是它真正的作用边界。

常见误解场景:

  • 写完 volatile 变量后,后续普通变量赋值仍可能被重排到其前面(只要不违反该 volatile 写与读之间的 happens-before)
  • synchronized 块内语句之间没有额外的 happens-before 保证,仅靠锁的获取/释放建立跨线程约束
  • 两个无共享变量、无同步操作的线程,即使逻辑上“先 A 后 B”,也不存在 happens-before,结果不可预测

6 条核心 happens-before 规则及其典型误用点

JSR-133 明确列出的规则中,最容易被忽略或错用的是这几条:

  • 程序顺序规则:同一个线程内,按代码顺序,每个操作 happens-before 之后的操作 —— 但仅限于该线程视角,不构成跨线程保证
  • 监视器锁规则:解锁 unlock() happens-before 后续对同一锁的加锁 lock() —— 注意是“后续”加锁,不是任意加锁;如果线程 B 没有真正 acquire 到锁,就不触发该规则
  • volatile 变量规则:对 volatile 变量的写 happens-before 后续对它的读 —— “后续”指在执行时序上发生得更晚,且必须是**同一个变量**;volatile int a 的写不保护 int b 的读写
  • 线程启动规则Thread.start() happens-before 该线程第一个动作 —— 但不保证主线程里 start() 之前的其他写操作对子线程可见,除非通过 final 字段、volatile 或锁传递
  • 线程终止规则:线程中所有操作 happens-before 其他线程检测到该线程已结束(如 t.join() 返回)—— 这是唯一能安全获取子线程最终状态的机制之一
  • 中断规则:对线程 interrupt() happens-before 被中断线程检测到中断(如 isInterrupted() 返回 true)—— 但不保证中断前的内存写一定可见,需配合同步手段

final 字段的 happens-before 特殊保障:构造安全的关键

对象构造完成(构造函数返回)时,对 final 字段的写,happens-before 于任何其他线程看到该对象引用后的读取 —— 这是 JVM 对 final 的硬性保证,不依赖同步,也不受重排序影响。

立即学习Java免费学习笔记(深入)”;

但前提是:

知料觅得
知料觅得

知料觅得-全新AI搜索引擎,一键直达结果

下载
  • 构造过程中没有泄露 this 引用(如在构造函数中启动线程、注册监听器、赋值给静态变量等)
  • 字段声明为 final,且只在构造函数内赋值一次
  • 读取方拿到的是通过合法途径发布的引用(比如经由 volatile、锁、安全发布容器如 ConcurrentHashMap

否则,即使字段是 final,也可能看到默认值或部分初始化状态。

为什么 synchronized 和 volatile 不等价?看 happens-before 链如何断裂

两者都建立 happens-before,但粒度和传播能力不同:

  • synchronized 建立的是“锁释放 → 锁获取”的跨线程链,可串联多个线程(A 释放 → B 获取 → B 释放 → C 获取),天然支持多跳传递
  • volatile 是“写 → 读”一对一绑定,无法中继:A 写 x,B 读 x 并写 y,C 读 y —— C 看不到 A 的写,除非 y 也是 volatile
  • 性能差异背后是内存屏障类型不同:volatile 写插入 StoreStore + StoreLoad,而 synchronized unlock 插入 StoreStore + StoreLoad + LoadLoad + LoadStore

一个典型断裂场景:用 volatile 标志位通知“数据就绪”,但未用 volatile 或锁保护实际数据本身,读线程可能看到标志为 true 却读到未更新的数据字段。

真正难的不是记住规则,而是判断哪条规则在你的具体调用路径中生效、有没有断链、有没有隐式依赖未被覆盖。多数并发 bug 都出在这里,而不是语法写错。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

646

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

553

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

173

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

205

2025.08.29

c++中volatile关键字的作用
c++中volatile关键字的作用

本专题整合了c++中volatile关键字的相关内容,阅读专题下面的文章了解更多详细内容。

69

2025.10.23

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

613

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

613

2023.08.10

Java 并发编程高级实践
Java 并发编程高级实践

本专题深入讲解 Java 在高并发开发中的核心技术,涵盖线程模型、Thread 与 Runnable、Lock 与 synchronized、原子类、并发容器、线程池(Executor 框架)、阻塞队列、并发工具类(CountDownLatch、Semaphore)、以及高并发系统设计中的关键策略。通过实战案例帮助学习者全面掌握构建高性能并发应用的工程能力。

89

2025.12.01

Golang处理数据库错误教程合集
Golang处理数据库错误教程合集

本专题整合了Golang数据库错误处理方法、技巧、管理策略相关内容,阅读专题下面的文章了解更多详细内容。

67

2026.02.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3.4万人学习

C# 教程
C# 教程

共94课时 | 8.9万人学习

Java 教程
Java 教程

共578课时 | 60.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号