【面试突击】硬件级别可见性问题面试实战(上)

🌈🌈🌈🌈🌈🌈🌈🌈
欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术的推送!

在我后台回复 「资料」 可领取编程高频电子书
在我后台回复「面试」可领取硬核面试笔记

文章导读地址:点击查看文章导读!

感谢你的关注!

🍁🍁🍁🍁🍁🍁🍁🍁

硬件级别可见性问题面试实战

这里为什么要了解一下可见性的底层原理呢?

因为对于可见性这块的内容,他并不是软件层面上的问题,而是硬件层面的问题,是底层的一些机制导致了可见性的问题,了解了底层的相关内容之后,我们的知识会更容易形成一个闭环,而不仅仅是停留于软件层面,对下层一无所知!

所以接下来聊一聊底层中到底是什么原因导致了不同线程之间出现这个可见性的问题

可见性硬件级别造成原因

首先,每一个处理器都有自己的寄存器,而线程对变量的读操作都是针对写缓冲进行的,因此这个可见性问题与 寄存器写缓冲 这两个硬件组件是有关联的

这里分别说一下寄存器和写缓冲 如何导致了可见性的问题

  • 多个处理器都在运行各自的线程的时候,如果其中一个处理器中的线程将某一个变量更新后的值放在寄存器中,那么其他处理器中的线程是没有办法看到这个更新后的值的,因为这个寄存器是各个处理器私有的,因此,寄存器会导致可见性的问题

  • 处理器运行的线程,对变量的写操作是针对写缓冲进行的,之后才会刷到主内存中,因此如果一个线程更新了变量,如果仅仅写入到了写缓冲充,还没有刷到主内存或高速缓存中,那么其他处理器中的线程是无法感知到这个变量的修改的,此时,导致可见性的问题

    即使这个写缓冲的数据的更新也同步到了自己的主内存或高速缓存里,并且将这个更新通知给了其他的处理器,但是其他处理器可能把这个更新放到无效队列中,并没有更新自己的高速缓存,此时仍然会导致可见性的问题

如下这个图:
在这里插入图片描述

MESI 协议

那么要实现多个处理器的共享数据的一致性,可以通过 MESI 协议来实现

根据具体底层硬件的不同,MESI 协议的具体实现也是不同的

这里说一种 MESI 协议的实现:通过将其他处理器高速缓存中 更新后的数据 拿到自己的高速缓存中更新一下,这样不同处理器之间的高速缓存中的数据就保持一致了,实现了可见性

在实现 MESI 协议的过程中,需要 两个关键的机制 来确保缓存的一致性:flush 和 refresh

  • flush

将自己更新的值刷新到高速缓存里去,让其他处理器在后续可以通过一些机制从自己的高速缓存里读到更新后的值

并且还会给其他处理器发送一个 flush 消息,让其他处理器将对应的缓存行标记为无效,确保其他处理器不会读到这个变量的过时版本

  • refresh

处理器中的线程在读取一个变量的值的时候,如果发现其他处理器的线程更新了变量的值,必须从其他处理器的高速缓存(或者是主内存)里,读取这个最新的值,更新到自己的高速缓存中

因此,在底层通过 MESI 协议、flush 处理器缓存和 refresh 处理器缓存来保证可见性的

总结一下就是,flush 是强制将更新后的数据从写缓冲器中刷新到高速缓存中去;refresh 是去感知到其他处理器更新了变量,主动从主内存或其他处理器的高速缓存中加载最新数据

那么举个例子,对于 volatile 变量来说:

volatile boolean flag = true;

当写 volatile 变量时,就会通过执行一个内存屏障,在底层会触发flush处理器缓存的操作,把数据刷到主内存中

当读 volatile 变量时,也会通过执行一个内存屏障,在底层触发refresh操作,从主内存中,读取最新的值

指令重排

指令重排的内容我们可以来了解一下,什么时候会发生指令重排

指令重排指的是我们写好的代码,在真正执行的时候,执行顺序可能会被重排序,如果重排序之后,在多线程的执行环境下,可能就会出现一些问题

什么时候会发生指令重排呢?

  • 编译期间

Java 中有两种编译器,一种是静态编译器(javac),另一种是动态编译器(JIT)

javac 负责把 .java 文件中的源代码编译为 .class 文件中的字节码,这个一般是程序写好之后进行编译的

JIT 是 JVM 的一部分,负责把 .class 文件中的字节码编译为 JVM 所在操作系统支持的机器码,一般在程序运行过程中进行编译

那么在编译期间,可能编译器为了提高代码的执行效率,会对指令进行重排,JIT 对指令重排还是比较多的

  • 处理器执行顺序

编译器编译好的指令,到真正处理器执行的时候,可能还会调整顺序

指令重排有什么规则约束呢?

上边讲过了一个 happens-before 原则,它定义了一些规则,只要符合 happens-before 中的规则的都不会进行指令重排

就比如说,下边代码的第三行不可能重排到上边,因为它的执行结果依赖了上边两行的执行结果,因此不会重排,但是前两行可能会重排:

int a = 1;
int b = 2;
int c = a + b;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/333291.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode热题100】【子串】和为 K 的子数组

题目 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1: 输入:nums [1,1,1], k 2 输出:2示例 2: 输入:nums [1,…

DataSheet文件解读

DataSheet文件解读 IC介绍Features [特征]Typical Applications [典型应用]MARKING DIAGRAMS [标记图]![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/77041875f8f6435fa856a8f9aded6867.png)ORDERING INFORMATION 【订购信息】Figure1: Pin Diagram 【…

蓝桥杯(C++ 矩形总面积 错误票据 分糖果1 三国游戏 分糖果2)

目录 一、矩形总面积 思路: 代码: 二、错误票据 思路: 代码: 三、分糖果1 思路: 代码: 四、三国游戏 思路: 代码: 五、分糖果2 思路: 代码:…

ROS2机器人开发入门

ROS2学习 文章目录 ROS2学习ROS2对比ROS1的区别架构API编译系统OS 通讯节点模型进程安装命令 创建功能包 节点话题:节点间传输数据的桥梁发布者Publisher订阅者SubscriberROS2话题示例-发布图像话题ROS2话题示例-订阅图像话题usb相机的标准驱动 服务服务器端客户端 …

如何压缩视频到50m以内?这几个参数设置了吗?

在我们的日常生活中,视频文件经常占据较大的存储空间,给我们存储和传输带来了困扰,那么如何将视频文件压缩至50m以下呢?下面就为大家分享三个实用的方法,轻松解决视频过大问题。 方法一:调整视频分辨率 视…

亚马逊鲲鹏系统:强大防指纹技术引领全自动账号管理新时代

亚马逊作为全球最大的电商平台之一,一直都很受客户欢迎,而亚马逊鲲鹏系统的全新推出,旨在解决买家账号过多时的管理难题。据了解,这一系统不仅能够有效防止账号关联,而且在保障每个账号独立运行的同时,还拥…

JAVA——数据类型与运算符

数据类型 注意事项:1.初始化操作是可选的, 但是建议创建变量的时候都显式初始化. 2.最后不要忘记分号, 否则会编译失败. 3.初始化设定的值为 10L , 表示一个长整型的数字. 10l 也可以. 4.float 类型在 Java 中占四个字节, 遵守 IEEE 754 标准. 由于表示的数据精度范…

k8s的坑,从这里开始

转载说明:如果您喜欢这篇文章并打算转载它,请私信作者取得授权。感谢您喜爱本文,请文明转载,谢谢。 以前刚接触k8s时踩了不少坑,比如这些: 问题1 1、在master节点使用kubectl命令时,报错&…

新手如何学习单片机入行?

新手如何学习单片机入行? 在开始前我有一些资料,是我根据网友给的问题精心整理了一份「单片机的资料从专业入门到高级教程」, 点个关注在评论区回复“888”之后私信回复“888”,全部无偿共享给大家!!&…

使用 Docker 部署 的WAF: 雷池社区版

Web应用防火墙(WAF)是保护网站不受恶意攻击的关键组件。 使用 Docker 部署雷池社区版,可以大大简化安全管理工作。 一、WAF 雷池社区版简介 雷池社区版是一种流行的开源 Web 应用防火墙,它提供基本的安全保护,如防止…

10个常考的前端手写题,你全都会吗?

前言 📫 大家好,我是南木元元,热爱技术和分享,欢迎大家交流,一起学习进步! 🍅 个人主页:南木元元 今天来分享一下10个常见的JavaScript手写功能。 目录 1.实现new 2.call、apply、…

CentOS 6.10 安装图解

特特特别的说明 CentOS发行版已经不再适合应用于生产环境,客观条件不得不用的话,优选7.9版本,8.5版本次之,最次6.10版本(比如说Oracle 11GR2就建议在6版本上部署)! 引导和开始安装 选择倒计时结…

python爬虫--网页代码抓取

我回来了。 目录 前言一、爬虫是什么?二、使用步骤代码讲解第一版第二版第三版 总结 前言 爬虫,第一章 一、爬虫是什么? 爬虫是指一种自动化程序,通常被用于互联网上的数据采集。这些程序会模拟人类用户的行为,通过…

(2023版)斯坦福CS231n学习笔记:DL与CV教程 (12) | 视觉模型可视化与可解释性(Visualizing and Understanding)

前言 📚 笔记专栏:斯坦福CS231N:面向视觉识别的卷积神经网络(23)🔗 课程链接:https://www.bilibili.com/video/BV1xV411R7i5💻 CS231n: 深度学习计算机视觉(2017&#xf…

【题解 优化dp】 B - Base Station Construction

题目描述: 分析: 当dp状态设定不好的时候,我们不妨从最简单的部分出发 设 f i f_i fi​表示必须在第i个点建设基站,并且i号点之前的线段全部满足要求时所需要的最小代价 为什么这么设呢? 这道题想要入手,…

数据结构Java版(2)——栈Stack

一、概念 栈也是一种线性数据结构,最主要的特点是入栈顺序和出栈顺序是相反的,操作时只能从栈顶进行操作,在Java中给我们提供了一个泛型栈——Stack,其中最常用的方法有: void push(E):进栈E pop():退栈E peek():查看…

Java中创建List接口、ArrayList类和LinkedList类的常用方法(一)

List接口 要了解List接口,就不得不说起Java的集合框架。 (该图来自菜鸟教程) Collection接口和Map接口 Java 集合框架主要包括两种类型的容器,集合Collection和图Map。 Collection接口代表了单列集合,它包含了一组…

并发编程知识点梳理

并发编程 在了解并发编程基本知识,先了解几本书,方便学习提高,分别为:java编程思想、企业应用架构模式、并发编程实战。 多线程中的设计模式有:Future、Master-Worker、生产者-消费者。 本次课程分为以下几部分进行…

js - - - - - getSelection 对光标和选区的操作

window.getSelection getSelection示例代码属性方法 getSelection 官方MDN地址 示例代码 <template><div>这里是一段默认的文字内容</div> </template> <script> export default {name: "Home",mounted() {document.addEventListen…

在PyCharm中创建Flask项目

在 PyCharm 中创建 Flask 项目的步骤如下&#xff1a; 打开 PyCharm&#xff0c;并选择 "Create New Project"&#xff08;新建项目&#xff09;。在弹出的窗口中&#xff0c;选择左侧的 "Python" 选项&#xff0c;然后选择右侧的 "Flask" 项目…