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

🌈🌈🌈🌈🌈🌈🌈🌈
欢迎关注公众号(通过文章导读关注:【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;

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(2023版)斯坦福CS231n学习笔记:DL与CV教程 (56) | 卷积神经网络

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

Django ORM 模糊查询实例解析

在 Django 中,对象关系映射 (ORM) 系统提供了一种强大而直观的数据库交互方式。本博文将深入探讨 Django ORM 中的高级单表查询方法和模糊查询选项,使开发人员能够高效地检索和操作数据。 模糊查询是一种非常有用的功能,允许我们根据特定条件…

谷达冠楠科技:抖音开网店新手小白可以卖的产品

随着互联网的发展,越来越多的人选择在网上开设自己的店铺。而抖音作为目前最火的短视频平台,也提供了开店的功能。那么,对于新手小白来说,抖音开网店可以卖哪些产品呢? 我们可以考虑的是服装类商品。抖音上有很多时尚博主&#x…

java httpclient Post

一、Maven引用httpclient <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.3</version> </dependency> 二、直接上代码 private void PostData(){CloseableHt…

基于Qt/C++的体质监测系统,体重秤,体脂秤,身体质量指数系统,Qt语音播报

目录导览 一、前言二、项目功能介绍三、源程序四、总结 一、前言 可以通过该项目练习的c、qt的知识&#xff0c;提高自己的项目实战经验。同时需要其他管理系统的&#xff0c;如超市购物系统&#xff0c;图书管理系统、实验设备管理系统、超市管理系统、学生管理系统、教师管理…

开发企业微信中的内嵌h5时如何开发与调试

前言&#xff1a; 在我们的项目中&#xff0c;开发企业微信内部的项目的话&#xff0c;分为两种&#xff0c;1种是直接开发企业微信的小程序&#xff0c;另一种则是企业微信内嵌我们的H5界面&#xff0c;我们这里讲一讲企业微信内嵌h5的方法与注意点。 1、开发h5项目 这点没有…

【洛谷 P2084】进制转换 题解(模拟+字符串)

进制转换 题目背景 无 题目描述 今天小明学会了进制转换&#xff0c;比如&#xff08;10101&#xff09;2 &#xff0c;那么它的十进制表示的式子就是 : 1*240*231*220*211*2^0&#xff0c; 那么请你编程实现&#xff0c;将一个M进制的数N转换成十进制表示的式子。 注意…

BGP最通俗易懂的讲解——路由反射器防环机制

路由反射器防环机制&#xff1a;Originator ID与Cluster List 一、Originator ID 该属性属于BGP的可选非过渡属性&#xff1b;Originator ID由RR产生&#xff0c;使用的Router ID的值标识路由的发送者&#xff0c;用于防止集群内产生路由环路&#xff1b;当一条路由第一次被RR…

《每天十分钟》-红宝书第4版-集合引用类型(三)

数组还有一些常见api,还有一种特别的定型数组 操作方法 concat() slice() splice() 注意 如果 slice()的参数有负值&#xff0c;那么就以数值长度加上这个负值的结果确定位置。比 如&#xff0c;在包含 5 个元素的数组上调用 slice(-2,-1)&#xff0c;就相当于调用 slice(3,4…

【从零开始学习Java重要知识 | 第三篇】暴打ReentrantLock底层源码

目录 前言&#xff1a; 前置知识&#xff1a; 什么是公平锁与非公平锁&#xff1f; 尝试自己构造一把锁&#xff1a; ReentrantLock源码&#xff1a; 加锁&#xff1a; 解锁&#xff1a; 总结&#xff1a; 前言&#xff1a; 在并发编程中&#xff0c;线程安全是一个重…

【Python 千题 —— 基础篇】参加聚会

题目描述 题目描述 我们向五名同学(Alan、Bob、Candy、Eric、Sandy)发送了各发送了一封聚会邀请邮件,Alan、Candy 与 Sandy 都表示会参加,Bob 与 Eric 都表示不会参加;对于会参加的同学,将会回复 “I’m xxx. I’ll come to the party.”,对于不参加的同学,将会回复 …

大数据工作岗位需求分析

前言&#xff1a;随着大数据需求的增多&#xff0c;许多中小公司和团队也新增或扩展了大数据工作岗位&#xff1b;但是却对大数据要做什么和能做什么&#xff0c;没有深入的认识&#xff1b;往往是招了大数据岗位&#xff0c;搭建起基础能力后&#xff0c;就一直处于重复开发和…

C#设计模式教程(7):适配器模式

适配器模式的定义 适配器模式(Adapter Pattern)是一种结构型设计模式,它允许不兼容的接口之间能够相互合作。适配器的作用是解决那些因接口不兼容而不能一起工作的类的问题,它通过包装一个类的接口转换成另一个期望的接口。 适配器模式主要分为两种: 类适配器(Class Ad…

鉴源实验室|自动驾驶仿真测试技术分析

01 引言 随着科技的不断发展&#xff0c;自动驾驶技术逐渐成为汽车行业的热门话题。然而&#xff0c;要将自动驾驶车辆投放到真实道路上之前&#xff0c;必须进行广泛的测试&#xff0c;以确保其在各种情况下都能安全可靠地运行。自动驾驶车辆的测试是一个复杂而昂贵的过程。…

细说CubeIDE——之建立一个工程

博主今天给大家带来新的一个软件&#xff0c;由于公司要上市&#xff0c;盗版软件不让装&#xff0c;IAR&#xff0c;KEIL律师函争相投递&#xff0c;博主只能老老实实把软件卸掉&#xff0c;苦逼工作还得干&#xff0c;怎么办&#xff1f; 你说怎么办&#xff1f;怎么办&#…

常用中间件漏洞

IIS6 IIS7 安装 控制面板-----打开关闭windows功能 添加角色-----添加IIS 启动之后访问localhost 复现 服务器换成IIS7 访问报错 大概就是缺少CGI模块 问题解决 添加php-cgi的路径 添加脚本映射 修改php.ini文件 将 cgi.fix_pathinfo1 然后设置一个图片 访问 在后缀加上/.…

如何使用JS逆向爬取网站数据

引言&#xff1a; JS逆向是指利用编程技术对网站上的JavaScript代码进行逆向分析&#xff0c;从而实现对网站数据的抓取和分析。这种技术在网络数据采集和分析中具有重要的应用价值&#xff0c;能够帮助程序员获取网站上的有用信息&#xff0c;并进行进一步的处理和分析。 基…

Linux第29步_安装“Notepad++”软件

STM32CubeProgrammer脚本文件的后缀为“.tsv”&#xff0c;ST公司官方也叫做FlashLayout。在烧写“TF-A固件”之前&#xff0c;我们需要用“Notepad”软件打开“后缀为.tsv”的脚本文件&#xff0c;根据需求决定哪些文件需要更新&#xff0c;设置好这个脚本文件。 .tsv是文本格…

使用延迟队列处理超时订单

延迟队列是一种更为高效和可控的方式来处理定时任务&#xff0c;特别是在需要处理超时订单这类场景时。延迟队列可以让你将任务按照延迟时间有序地执行&#xff0c;而不需要通过轮询的方式频繁地检查订单表。 在Java中&#xff0c;可以使用Delayed接口和DelayQueue来实现延迟队…

C++ 之LeetCode刷题记录(十三)

&#x1f604;&#x1f60a;&#x1f606;&#x1f603;&#x1f604;&#x1f60a;&#x1f606;&#x1f603; 开始cpp刷题之旅。 依旧是追求耗时0s的一天。 70. 爬楼梯 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可…