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

Java-重排序,happens-before 和 as-if-serial 语义

目录

  • 1. 如何解决重排序带来的问题
  • 2. happens-before

1. 如何解决重排序带来的问题

对于编译器,JMM 的编译器重排序规则会禁止特定类型的编译器重排序。对于处理器重排序,JMM 的处理器重排序规则会要求编译器在生成指令序列时,插入特定类型的内存屏障(Memory Barries / Memory Fence)指令,通过内存屏障指令来禁止特定类型的处理器重排序。

由于常见的处理器内存模型比 JMM 要弱,Java 编译器在生成字节码时,会在执行指令序列的适当位置插入内存屏障来限制处理器的重排序。同时,由于各种处理器内存模型的强弱不同,为了在不同的处理器平台向程序员展示一个一致的内存模型,JMM 在不同的处理器中需要插入的内存屏障的数量和种类也不同。

CPU内存屏障

  1. LoadLoad:禁止读和读的重排序;
  2. StoreStore:禁止写和写的重排序;
  3. LoadStore:禁止读和写的重排序;
  4. StoreLoad:禁止写和读的重排序。

Java内存屏障

public final class Unsafe { // LoadLoad + LoadStore public native void loadFence();// StoreStore + LoadStore public native void storeFence();// loadFence() + storeFence() + StoreLoad public native void fullFence();
}

在这里插入图片描述
在这里插入图片描述

2. happens-before

JMM 使用 happens-before 规则来阐述操作之间的内存可见性,以及什么时候不能重排序。

在 JMM 中, 如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须要存在 happens-before 关系。换个角度来说,如果A happens-before B,则意味着A的执行结果必须对B可见,也就是保证跨线程的内存可见性。

其中,4条规则与程序员密切相关。

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

举个栗子

假设线程 A 执行 writer() 方法之后,线程 B 执行 reader() 方法。根据 happens-before 规则,这个过程建立的 happens-before 关系可以分为 3 类:

  1. 根据顺序规则,1 happens-before 2,3 happens-before 4;
  2. 根据 volatile 规则,2 happens-before 3;
  3. 根据 happens-before 的传递性规则,1 happens-before 4。
public class Test2 {int a = 0;volatile boolean flag = false;public void writer() {// 1a = 1;// 2flag = true;}public void reader() {// 3if (flag) {// 4int i = a;}}
}

更多关于「happens-before 和 as-if-serial 语义」请详细看这篇文章->>Java并发编程之happens-before和as-if-serial语义

http://www.lryc.cn/news/20708.html

相关文章:

  • Nginx安装及介绍
  • 【华为OD机试模拟题】用 C++ 实现 - 寻找路径 or 数组二叉树(2023.Q1)
  • LINUX学习记录
  • 华为OD机试用Python实现 -【狼羊过河 or 羊、狼、农夫过河】(2023-Q1 新题)
  • 【SAP Abap】X-DOC:SAP ABAP 语法更新之Open SQL
  • leetcode 困难 —— 数组中的逆序对(分治法)
  • 02.24:图片的风格转换
  • [SSD综述 1.3] SSD及固态存储技术半个世纪发展史
  • PAT 1023 组个最小数(分数20)题目有bug
  • QML 中的 5 大布局
  • 使用Python进行数据分析——线性回归分析
  • 我眼中的柔宇科技
  • Allegro如何快速把视图居中显示操作指导
  • 搜索相关功能
  • 【从零开始制作 bt 下载器】一、了解 torrent 文件
  • SystemVerilog-时序逻辑建模(5)多个时钟和时钟域交叉
  • 基本中型网络的仿真(RYU+Mininet的SDN架构)-以校园为例
  • 西北工业大学大学物理(II)期末试题选填解析2021-2022
  • 【USB】windows热插拔通知接口分析
  • CMake入门
  • python中一种编写config文件并及时更新的方法
  • 基于Windows下离线安装当前最新Arduino ESP32 SDK(2.0.7)固件开发包
  • Android 9.0 app添加校验锁(输入密码才能进入app)
  • 注意力机制详解系列(二):通道注意力机制
  • 动态规划-规划兼职工作
  • Redis学习笔记(二)Redis基础(基于5.0.5版本)
  • Ancaonda常用cmd命令总结
  • yolov5_reid【附代码,行人重识别,可做跨视频人员检测】
  • 多模态预训练模型综述
  • 华为OD机试题,用 Java 解【玩牌高手】问题