happens-before原则与内存屏障

2023-11-03

1. happens-before原则定义

  • 编译器和处理器会对我们程序优化而进行指令重排,但需要保证前一个操作结果对后一个依赖操作可见(其实只是在单线程下能保证),否则就禁止指令重排

1.1 指令重排带来的问题

  • 虽然指令重排满足happens-before原则但这个只能保证单线程下结果具有一致性。
  • 在多线程下,指令重排会导致很严重的并发错误,会导致结果不具有一致性
  • 多线程下想要结果也满足一致性,则需要加入内存屏障来解决指令重排的问题

2. 内存屏障

2.1 分类

  • Load Barrier:在读指令之前插入读屏障,可以让高速缓存中的数据失效,重新从主存加载数据
  • Store Barrier:在写指令之后插入写屏障,能让写入缓存的最新数据写回主内存

2.2 详细种类

  • LoadLoad 屏障 
    • Load1,Loadload,Load2 
    • 确保Load1所要读入的数据能够在被Load2和后续的load指令访问前读入。
  • StoreStore 屏障
    • ​​​​​​​Store1,StoreStore,Store2 
    • 确保Store1的数据在Store2以及后续Store指令操作相关数据之前对其它处理器可见(例如向主存刷新数据)
  • LoadStore 屏障 ​​​​​​​
    • Load1; LoadStore; Store2 
    • 确保Load1的数据在Store2和后续Store指令被刷新之前读取。
  • StoreLoad 屏障 ​​​​​​​
    • Store1; StoreLoad; Load2 
    • 确保Store1的数据在被Load2和后续的Load指令读取之前对其他处理器可见。

3. volatile关键字

3.1 volatile原理

通过内存屏障来防止指令重排,从而实现可见性和有序性

  • 在每个volatile写操作的前面插入一个StoreStore屏障。
  • 在每个volatile写操作的后面插入一个StoreLoad屏障。
  • 在每个volatile读操作的后面插入一个LoadLoad屏障。
  • 在每个volatile读操作的后面插入一个LoadStore屏障。

3.2 简要说明

  • volatile读前插入读屏障,写后插入写屏障,避免CPU重排导致的问题,实现了多线程之间的数据可见性

4. 内存屏障和缓存一致性

内存屏障会导致CPU缓存刷新,刷新时,会遵循缓存一致性协议

  • lock:解锁时,jvm会强制刷新CPU缓存,导致当前线程更改,对其他线程可见
  • volatile:在标记volatile的字段进行写操作时,会强制刷新CPU缓存,在标记为volatile的字段,每次读取都是直接读内存
  • final:即使编译器在final写操作后,会插入内存屏障,来禁止重排序,保证可见性

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

happens-before原则与内存屏障 的相关文章

随机推荐

  • 完美解决移动端滚屏问题

    背景 移动端开发有弹出框时 下面页面还是可以滚动 本身也不是问题 但是有时候需要弹框出现 底部禁止滚动 如果需要 以下代码可以帮你实现效果 在需要弹窗的代码里 调用stopBodyScroll true 在关闭弹窗代码里 调用stopBod
  • macbook卸载软件时,显示软件已锁定解决办法

    macbook卸载软件时 显示软件已锁定解决办法 1 点开启动台终端 2 输入 bin ls dleo 你想要卸载的软件路径 可以直接从应用程序里面拖进来 输完后点回车 你可以看到 drwxr xr x 3 root admin 99 12
  • OpenGL3D图形绘制/纹理映射

    1 3D图形绘制 3D图形也是由2D的面片组合而成 一个需要注意的问题是所有的面片绘制要么是逆时针要么是顺时针 因此每三个点确定一个三角形或者每四个点确定一个四边形 再有余下的点时 按新的形状处理 以下以一个旋转的金字塔和立方体为例 int
  • 手把手教python发送邮件

    使用python内置模块 smtplib和email进行邮件发送 其中smtplib模块负责发送邮件 而email模块负责构造邮件内容 一 基本用法介绍 1 smtplib模块 1 引入smtplib模块 import smtplib 2
  • OpenStack之仪表盘服务(Dashboard)

    一 Dashboard的基本 1 概念 OpenStack云计算平台可以通过命令行管理工具使用 或者其他应用通过应用程序接口被其他程序调用 但是都较为麻烦 不够直观 那么Dashboard随机应运而生了 其本质是一个web前端控制台 主要功
  • 【Vue3】跨域问题 [The value of the ‘Access-Control-Allow-Origin‘ header in the response must not be the..]

    场景 vue 项目中 axios 请求数据的时候请求失败 出现跨域问题 报错信息 The value of the Access Control Allow Origin header in the response must not be
  • Maven报错无法解析插件

    某天本人创建好一个Maven项目写导入依赖的时候给我跳出一个错误 说一些Maven插件无法解析 虽说这是个小问题 但这个问题直接卡了一个小时的说 具体出错效果可以参考下图 注意哦 我这是在没网的情况下 有网的话maven会直接给你在中央仓库
  • 【LeetCode每日刷题】一行代码实现《2的幂》

    一 题目 给你一个整数 n 请你判断该整数是否是 2 的幂次方 如果是 返回 true 否则 返回 false 如果存在一个整数 x 使得 n 2x 则认为 n 是 2 的幂次方 输入 输入一个整数 输出 输出True或者False 二 例
  • matlab语音去除白噪声_基于的MATLAB的语音加噪去噪处理

    龙源期刊网 http www qikan com cn 基于的 MATLAB 的语音加噪去噪处理 作者 张大林 何威 李瑶瑶 来源 中国科技博览 2019 年第 01 期 摘 要 语音是语言的声学表现 是人类交流信息最自然 最有效 最方便的
  • 【SpringCloud】Spring cloud Alibaba Sentinel 降级规则

    文章目录 1 概述 2 服务降级 2 1 RT 2 2 异常比例 2 3 异常数 1 概述 本章是接着上一章讲解 SpringCloud Spring cloud Alibaba Sentinel 服务降级 阿里版本Hystrix 2 服务
  • 寻找URL、域名、网站名对应区别和组合关系

    URL URL由三部分组成 资源类型 存放资源的主机域名 资源文件名 也可认为由4部分组成 协议 主机 端口 路径 例如 百度一下 你就知道 http 协议 www 服务器 baidu com 域名 表示根目录 也就是平常我们文件夹的D 是
  • 傅里叶变换回顾与总结

    傅里叶变换回顾与总结对傅里叶变换进行回顾总结 遗忘 要用的时候回顾此浓缩版即可 内容来源于不同出处 函数名称 符号使用不是十分统一 一维二维表达同时存在 略表歉意 1 两个前提线性性 两个信号加权和输出为它们分别输出和的加权 权值为标量 时
  • openwrt无线中继WIFI的设置--WR703N

    主要是配置两个文件 一 vi etc config wireless 在 option disabled 1 这一行下面加入OpenWRT连接WIFI的配置 内容如下 config wifi iface wlan0 option devic
  • QGIS之十四连接PostGIS数据库

    背景 有时候我们需要用到qgis来连接PostGIS数据库进行一些可视化或者空间分析的操作 那我们来了解QGIS如何连接PostGIS数据库 步骤 1 新建连接 在qgis的浏览器窗口中找到PostGIS 右键新建连接 2 输入数据库参数
  • 埋点的机制

    埋点事件 所谓埋点事件 就是埋点需要采集的活动 activity 埋点一般会获取三种事件 曝光事件 页面停留事件 点击事件 曝光事件 主要记录页面被用户浏览次数 上报机制 用户成功进入一个页面时记录一次曝光事件 刷新一次页面也会上报一次 如
  • 使用R语言进行回归诊断

    人们提出所谓回归诊断的问题 其主要内容有 关于误差项是否满足 独立性 等方差性 正态性 选择线性模型是否合适 是否存在异常样本 回归分析的结果是否对某些样本依赖过重 也就是回归模型是否具有稳定性 自变量之间是否存在高度相关 即是否存在多重共
  • MySQL数据库增删改查

    前言 MySQL准确来说是一款开源关系型数据库管理系统 支持多种数据库类型 包括整型 字符型 日期 时间型等 它还支持BLOB 二进制大对象 和文本类型 使得存储各种类型的数据变得更加便捷 平时工作中主要操作无非是增删改查 本文将通过Nav
  • c++学习之虚析构和纯虚析构

    1 多态使用时 如果子类中有属性开辟到堆区 那么父类指针在释放时无法调用子类的析构代码 解决方法 将父类中的析构函数改为虚析构或者是纯虚析构 2 虚析构和纯虚析构共性 1 都可以解决父类指针无法释放子类对象的问题 2 都需要有具体的函数实现
  • vue.js水平时间轴_用Vue.js制作的简单水平时间轴组件

    vue js水平时间轴 Vue水平时间线 Vue Horizontal Timeline a simple horizontal timeline component made with Vue js 一个由Vue js制作的简单水平时间轴
  • happens-before原则与内存屏障

    1 happens before原则定义 编译器和处理器会对我们程序优化而进行指令重排 但需要保证前一个操作结果对后一个依赖操作可见 其实只是在单线程下能保证 否则就禁止指令重排 1 1 指令重排带来的问题 虽然指令重排满足happens