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

news/2024/12/29 19:37:12/

目录

  • 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.ppmy.cn/news/28203.html

相关文章

Python控制CANoe使能TestCase

前面介绍了多种CANoe配置下的dbc文件添加,常见的配置我们能够常用的就是testcase的使能和环境变量的设置,针对于环境变量的问题,我们下次再进行详聊,今天主要聊一下测试脚本的使能。在做这块之前,我们第一步就需要了解我们的测试脚本的层级是都包含有哪些? 一、测试脚本结…

typedef在c语言中的作用

在 C 语言中,typedef 是一个非常有用的关键字,用于给数据类型定义一个新的名字。typedef 的作用有以下几个方面: 定义新类型名:typedef 可以定义一个新的数据类型名称,使得该类型名称可以在程序中使用。这样可以提高代…

C语言——指针进阶

C语言——指针进阶1. 字符指针2. 指针数组3. 数组指针 <33.1 数组指针的定义3.2 &数组名VS数组名3.3 数组指针的使用4. 函数指针5. 函数指针数组6. 指向函数指针数组的指针7. 回调函数❤️ 学习这篇文章&#xff0c;要知道的基础知识 指针就是个变量&#xff0c;用来存放…

C语言学习笔记——程序环境和预处理

目录 前言 一、程序环境 1. 翻译环境 1.1 主要过程 1.2 编译过程 2. 运行环境 二、预处理 1. 预定义符号 2. #define 2.1 #define定义标识符 2.2 #define定义宏 2.3 命名约定和移除定义 3. 条件编译 4. 文件包含 结束语 前言 每次我们写完代码运行的时候都…

【大厂算法系列】编码手写顺序表相关功能,线性结构核心知识点详细剖析

章节目录 什么是线性表什么是顺序表顺序表简介初始化和判空判满功能实现顺序表实现之指定位置数据的增加与遍历操作顺序表实现删除指定位置的元素与修改操作顺序表实现扩容操作顺序表使用泛型适应多种类型数据什么是线性表 在第二章里我们说到的两个元素有**“一对一”** 逻辑关…

产品经理有必要考个 PMP吗?(含PMP资料)

现在基本上做产品的都有一个PMP证件&#xff0c;从结果导向来说&#xff0c;不对口不会有这么大范围的人来考&#xff0c;但是需要因地制宜&#xff0c;在公司内部里&#xff0c;标准程序并不流畅&#xff0c;产品和项目并不规范&#xff0c;关系错综复杂。 而产品经理的职能又…

python的所有知识点(含讲解),不看就亏死了

目录 简介 特点 搭建开发环境 版本 hello world 注释 文件类型 变量 常量 数据类型 运算符和表达式 控制语句 数组相关 函数相关 字符串相关 文件处理 对象和类&#xff0c;注&#xff1a;不是那个对象&#xff01;&#xff01;&#xff01;&#xff01;&…

20_FreeRTOS低功耗模式

目录 低功耗模式简介 STM32低功耗模式 Tickless模式详解 Tickless模式相关配置 实验源码 低功耗模式简介 很多应用场合对于功耗的要求很严格,比如可穿戴低功耗产品、物联网低功耗产品等。 一般MCU都有相应的低功耗模式,裸机开发时可以使用MCU的低功耗模式。 FreeRTOS也…