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

什么是 Java 的 happens-before 规则?

Java 的 Happens-Before 规则

Happens-Before是 Java 内存模型(JMM)中用于描述操作之间可见性有序性的核心概念。它定义了一套规则,确保一个操作的结果对另一个操作是可见的。


核心概念

Happens-Before 关系:如果操作 Ahappens-before操作 B,那么:

  • 操作 A 的执行结果对操作 B 可见
  • 操作 A 的执行顺序在操作 B 之前

八大 Happens-Before 规则

1. 程序次序规则

单线程内,按照代码顺序,书写在前面的操作 happens-before 书写在后面的操作。

publicvoidmethod(){inta=1;// 1intb=2;// 2intc=a+b;// 3// 1 happens-before 2// 2 happens-before 3// 1 happens-before 3(传递性)}

2. 管程锁定规则

一个unlock操作 happens-before 后续对同一个锁lock操作。

classSharedResource{privateintcount=0;// 线程 A 执行publicvoidincrement(){synchronized(this){count++;// unlock happens-before 下一次 lock}}// 线程 B 执行publicintgetCount(){synchronized(this){returncount;// 能看到线程 A 的修改}}}

3. volatile 变量规则

对一个volatile变量的写操作happens-before 后续对这个变量的读操作

classVolatileExample{privatevolatilebooleanflag=false;// 线程 Apublicvoidwriter(){flag=true;// volatile 写}// 线程 Bpublicvoidreader(){if(flag){// volatile 读,能看到线程 A 的写入// 执行某些操作}}}

4. 线程启动规则

Thread.start()方法 happens-before 该线程的每一个动作。

publicclassStartRule{privateintx=0;publicstaticvoidmain(String[]args){StartRuleexample=newStartRule();example.x=10;// 主线程设置Threadthread=newThread(()->{// 能看到 x = 10System.out.println(example.x);});thread.start();// start() happens-before 线程执行}}

5. 线程终止规则

线程中的所有操作都 happens-before 其他线程从该线程的join()方法成功返回。

publicclassJoinRule{privateintresult=0;publicstaticvoidmain(String[]args)throwsInterruptedException{JoinRuleexample=newJoinRule();Threadthread=newThread(()->{example.result=42;// 线程内操作});thread.start();thread.join();// join() 返回 happens-before 后续操作// 能看到 result = 42System.out.println(example.result);}}

6. 线程中断规则

对线程interrupt()方法的调用 happens-before 被中断线程的代码检测到中断事件。

publicclassInterruptRule{publicstaticvoidmain(String[]args){Threadthread=newThread(()->{while(!Thread.currentThread().isInterrupted()){// 工作中...}// 能检测到中断信号System.out.println("Thread interrupted");});thread.start();thread.interrupt();// interrupt() happens-before 检测到中断}}

7. 对象终结规则

一个对象的初始化完成(构造函数执行结束)happens-before 它的finalize()方法的开始。

publicclassFinalizeRule{privateintvalue;publicFinalizeRule(intvalue){this.value=value;// 构造函数执行}@Overrideprotectedvoidfinalize()throwsThrowable{// 能看到构造函数中设置的 valueSystem.out.println("Finalize: "+value);super.finalize();}}

8. 传递性规则

如果操作 A happens-before 操作 B,且操作 B happens-before 操作 C,那么操作 A happens-before 操作 C。

classTransitivityRule{privatevolatileintx=0;privateinty=0;// 线程 ApublicvoidthreadA(){x=1;// 1y=2;// 2}// 线程 BpublicvoidthreadB(){intr1=y;// 3intr2=x;// 4}}

分析

  • 如果yvolatile,则2 happens-before 3
  • 根据程序次序规则,1 happens-before 2
  • 根据传递性,1 happens-before 3
  • 因此线程 B 能看到x = 1

实际应用示例

示例1:双重检查锁

publicclassSingleton{privatestaticvolatileSingletoninstance;// volatile 关键publicstaticSingletongetInstance(){if(instance==null){// 第一次检查synchronized(Singleton.class){if(instance==null){// 第二次检查instance=newSingleton();// new Singleton() 包含:// 1. 分配内存// 2. 初始化对象// 3. 将引用指向内存// volatile 禁止 2 和 3 重排序}}}returninstance;}}

happens-before 分析

  • volatile 写 happens-before volatile 读
  • 保证其他线程能看到完全初始化的对象

示例2:生产者-消费者

classProducerConsumer{privatevolatilebooleanhasData=false;privateintdata;// 生产者publicvoidproduce(intvalue){data=value;// 1hasData=true;// 2 - volatile 写}// 消费者publicintconsume(){while(!hasData){// 3 - volatile 读// 等待}returndata;// 4 - 能看到 1 的结果}}

happens-before 分析

  • 2 happens-before 3(volatile 规则)
  • 1 happens-before 2(程序次序规则)
  • 3 happens-before 4(程序次序规则)
  • 传递性:1 happens-before 4
  • 因此消费者能看到生产者设置的 data

总结

规则关键点应用场景
程序次序单线程顺序保证单线程内执行顺序
管程锁定unlock → locksynchronized 块间可见性
volatile写 → 读状态标志、单例模式
线程启动start() → 线程动作线程初始化数据传递
线程终止线程动作 → join()获取线程执行结果
线程中断interrupt() → 检测中断优雅停止线程
对象终结构造完成 → finalize()对象清理
传递性A→B, B→C ⇒ A→C复合场景分析

核心思想:happens-before 规则不需要所有操作都按顺序执行,只需要保证必要的顺序关系,从而在保证正确性的前提下,允许编译器和处理器进行优化重排序。

http://www.cnnetsun.cn/news/1267310.html

相关文章:

  • Qwen2.5-VL-7B-Instruct一文详解:如何构造高质量多模态SFT训练数据
  • 智能硬件集成:SenseVoice-Small ONNX嵌入式设备语音识别方案
  • 深入解析fio:从基础使用到高级性能调优
  • ChatGPT私有化部署实战:从模型加载到API服务优化
  • 突破小爱音箱音乐限制:XiaoMusic自由播放解决方案全攻略
  • Flutter 三方库 ethiopian_datetime 鸿蒙适配指南 - 实现东非特殊历法转换、在 OpenHarmony 上打造全球化本地应用实战
  • 基于立创开发板与R7FA6E2BB3CNE的BH1750FVI光照传感器I2C驱动移植与数据采集实战
  • xxl-job升级避坑指南:2.2.0到2.3.1常见问题及解决方法
  • TTL与非门电路实战:从原理图到面包板搭建全流程(附常见问题排查)
  • 小龙虾(OpenClaw)配置第三方中转Api的完整图文教程
  • Dify 2026多模态向量对齐失败诊断图谱(含t-SNE可视化热力图+CLIP空间偏移校准公式)
  • 丹青识画系统在网络安全中的应用:恶意图像内容智能识别
  • java ssm基于J2EE线上医药用品分销系统设计与实现论文
  • ComfyUI-VideoHelperSuite高效实践指南:VHS_VideoCombine专业技巧与工作流优化
  • USB供电的宽量程高精度直流电流采集仪设计
  • Windows下Python报错:ModuleNotFoundError: No module named ‘readline‘的终极解决方案
  • Z-Image-Turbo-辉夜巫女入门必看:LoRA模型 vs 基座模型差异及Z-Image-Turbo适配要点
  • Qwen3-Embedding-4B一文详解:文本向量化底层逻辑、余弦相似度计算与GPU优化要点
  • 深入解析 Android Room 数据库的 Journal Mode 选择与优化策略
  • buildAdmin实战:从安装到代码生成器的全流程解析
  • SecGPT-14B惊艳输出:对某0day漏洞PoC代码的逐行安全语义解析
  • cv_resnet18_ocr-detection应用案例:截图文字识别与批量处理技巧
  • Gemma-3 Pixel Studio效果实测:同一张图5次不同提问获得专业级分层解读
  • 从4个维度彻底解决洛雪音乐六音音源失效难题
  • 贾子理论体系的六大核心优势:从底层原创到文明级落地的东方元理论
  • 拯救数字遗产:CefFlashBrowser全场景复活Flash内容指南
  • EDA工具实战:在CentOS 6.5上部署Cadence INNOVUS 15.20的完整指南
  • Gemma-3-12b-it效果集:交通标志图识别+法规解读+事故责任推演示例
  • UDOP-large部署教程:GPU显存监控与OOM异常排查指南
  • SDXL 1.0数字人:语音驱动面部动画生成