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

Java高频面试之并发编程-14

hello啊,各位观众姥爷们!!!本baby今天又来报道了!哈哈哈哈哈嗝🐶

面试官:指令重排有限制没有?happens-before 又是什么?


在并发编程中,指令重排(Instruction Reordering)happens-before 原则是确保多线程程序正确性的核心机制。


一、指令重排的限制

1. 指令重排的定义

编译器或处理器为了优化性能,可能在不改变单线程执行结果的前提下,调整指令的执行顺序。例如:

int a = 1;  // 指令1
int b = 2;  // 指令2

编译器可能先执行指令2再执行指令1,因为这对单线程结果无影响。

2. 重排的限制

在多线程环境下,无限制的指令重排会导致数据不一致。因此,JMM(Java内存模型)通过 happens-before原则 限制重排,确保以下操作的顺序性:

  • 写后读:若操作A写变量,操作B读该变量,则A必须在B之前。
  • 写后写:若操作A和B都写同一变量,A必须在B之前。
  • 读后写/读:若操作A读变量,操作B写或读该变量,则需确保可见性。
3. 禁止重排的场景
  • volatile变量:对volatile变量的读写操作不能被重排。
  • 锁操作:加锁(monitorenter)和解锁(monitorexit)之间的代码不能被重排到锁外。
  • final字段:构造函数中对final字段的写入,不会被重排到构造函数外。

二、happens-before原则

1. 定义

happens-before是JMM定义的操作间的偏序关系,确保前一个操作的结果对后续操作可见。若操作A happens-before操作B,则:

  • A的执行结果对B可见。
  • A的执行顺序排在B之前。
2. 核心规则
规则描述示例
程序顺序规则单线程中,代码书写顺序的操作happens-before后续操作。int x=1; int y=x+1;x=1 happens-before y=x+1
volatile规则volatile变量的写操作happens-before后续对该变量的读操作。volatile boolean flag=false;flag=true写happens-beforeflag读。
锁规则解锁操作happens-before后续的加锁操作。synchronized(lock){...} → 解锁happens-before下一个线程的加锁。
线程启动规则线程的start()调用happens-before该线程内的任何操作。thread.start() → 线程内run()中的操作可见start()前的修改。
线程终止规则线程中的所有操作happens-before其他线程检测到该线程终止(如join()返回)。thread.join() → 主线程能看到线程内所有修改。
传递性规则若A happens-before B,且B happens-before C,则A happens-before C。用于链式操作的有序性保证。
3. 实际应用
  • 双重检查锁定(DCL)

    public class Singleton {private static volatile Singleton instance; // 必须用volatilepublic static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton(); // 禁止重排初始化与赋值}}}return instance;}
    }
    

    volatile防止指令重排,确保对象完全初始化后才赋值给instance

  • 线程间通信

    volatile boolean flag = false;
    // 线程1
    data = 42;
    flag = true; // 写操作happens-before线程2的读操作
    // 线程2
    while (!flag); // 等待flag为true
    System.out.println(data); // 确保看到data=42
    

    volatile保证线程1的写操作对线程2可见。


三、happens-before与内存屏障

1. 内存屏障的作用

JVM通过插入内存屏障(Memory Barrier)指令实现happens-before规则,限制指令重排。常见屏障类型:

  • LoadLoad:确保当前读操作前的所有读操作完成。
  • StoreStore:确保当前写操作前的所有写操作完成。
  • LoadStore:确保当前读操作后的所有写操作完成。
  • StoreLoad:确保当前写操作后的所有读/写操作完成(开销最大)。
2. volatile的实现
  • 写操作:在写volatile变量后插入StoreStoreStoreLoad屏障。
  • 读操作:在读volatile变量前插入LoadLoadLoadStore屏障。

四、总结

机制核心作用关键点
指令重排优化性能,但受限于happens-before规则。单线程结果不变,多线程需同步机制保证可见性。
happens-before定义操作间的可见性和顺序性,限制指令重排。通过程序顺序、锁、volatile等规则确保多线程正确性。
内存屏障物理实现happens-before规则,强制刷新内存和限制重排。volatile、锁等同步机制的底层依赖。

开发建议

  • 优先使用volatilesynchronized、原子类等工具显式管理同步。
  • 理解happens-before规则,避免隐式依赖指令顺序。
  • 复杂场景结合工具(如java.util.concurrent包)简化并发控制。
    在这里插入图片描述

相关文章:

  • 设备管理系统深度测评:如何用 AI 知识库实现故障智能诊断?
  • 沃伦森电容器支路阻抗特性监控系统 电容器组智能健康管理专家
  • 模拟内存管理
  • 工程管理系统简介 工程管理系统源码 java工程管理系统 工程管理系统功能设计 从架构到实操
  • 若依框架Ruoyi-vue整合图表Echarts中国地图标注动态数据
  • TCP/IP和OSI对比
  • 果汁厂通信革新利器:Ethernet/IP转CANopen协议网关
  • 网盘解析工具更新,支持UC网盘!!
  • 从艾米・阿尔文看 CTO 的多面特质与成长路径
  • 使用DEEPSEEK快速修改QT创建的GUI
  • LLM 论文精读(三)Demystifying Long Chain-of-Thought Reasoning in LLMs
  • 深度学习笔记41_调用Gensim库训练Word2Vec模型
  • 什么是:Word2Vec + 余弦相似度
  • 又双叒叕想盘一下systemd
  • Lua从字符串动态构建函数
  • Pandas比MySQL快?
  • 全国青少年信息素养大赛 Python编程挑战赛初赛 内部集训模拟试卷三及详细答案解析
  • 计算机科技笔记: 容错计算机设计01 概述 教材书籍 课程安排 发展历史
  • 不止于观赏:3D 全景漫游的多元价值​
  • MySQL 8.0 OCP认证考试题库持续更新
  • 马上评丨行人转身相撞案:走路该保持“安全距离”吗
  • 重庆党政代表团在沪考察,陈吉宁龚正与袁家军胡衡华共商两地深化合作工作
  • 中国中古史集刊高质量发展论坛暨《唐史论丛》创刊四十周年纪念会召开
  • 现场|万米云端,遇见上博
  • 苹果用户,安卓来“偷心”
  • 巴基斯坦军方:印度向巴本土及巴控克什米尔发射导弹