并发-JMM-CPU缓存一致性协议MESI

回顾

指令重排
在这里插入图片描述
第一V读,都不能指令重排;第二个V写,都不能指令重排
普通读写,写读都会发生指令重排,V写+普通读写会发生指令重排,普通读写+V读会发生指令重排

CPU缓存一致性协议MESI

java—》cpu的执行过程

.class文件–经过类装载子系统----装载到元空间----根据.class文件会在堆里生成Class结构化对象----创建线程栈----线程创建后机会执行.class中定义的方法的字节码—操作字节码的过程中需要程序计数器和解释执行器/jit优化转为汇编指令【字节码翻译成汇编指令,时间比较长】—再翻译成二进制供CPU读取【时间比较短】

CPU怎么知道什么时候调用这个线程呢?
答:
CPU用的是内核线程模型,在操作系统底层维护OS线程变量池【维护有线程表,当CPU调到该线程时,二进制就会方法CPU上执行 】,该线程池与JVM虚拟机栈是一对一的

volatile的加入,字节码显示会有lock前置锁----》触发硬件缓存锁定机制【总线锁、缓存一致性协议】
总线锁:早期使用总线保证缓存一致
早起CPU要是多核的话,导致两个CPU共同操作一个变量X【两个CPU都是读的话没问题】,要是两个CPU都对变量进行写的话,就会导致不知道执行哪个CPU的问题,所以前期就采用
lock前缀加总线锁
【总线的作用:CPU跟内存之间访问是通过总线进行的】
所以前期在总线上加lock前缀锁的时候就会影响CPU跟内存进一步的信息交流进而影响CPU的执行【CPU就类似于单核,CPU的多核效果发挥不出来】,导致性能很低

缓存一致性协议:
在这里插入图片描述
加入总线嗅探机制
CPU启动后采用监听模式一直监听总线

volatile可见性原理

加volatile后会在汇编层面加lock前缀,lock前缀就会触发缓存一致性协议,即时有多个线程同时进行操作,也能保持可见性
线程A与线程B从主存读取数据放到各自的工作内存,各标记S状态【共享,只有一个读取得时候是标记E状态(独占)】,当一个线程改了【改之前会加锁(锁缓存换行,缓存行为64字节大小,原子安全的;要是缓存行装不下,缓存一致性协议就会升级为总线锁),由总线去裁决哪个线程加锁】,改完后就会更改状态为M ,并写回主存,因为嗅探机制另一个线程就会嗅探到数据已更改就会改状态为I从而舍弃从新重主存读取数据

/*第一次把MESI理解的这么透彻! 举个栗子,使用volatile关键字修饰的属性,当两个或多个线程通过总线去主内存获取这个属性的值时,会对总线加一个lock前缀,早期总线加了lock前缀的话,其他线程都会阻塞,不能获取属性值,导致性能非常低。进而就设计出了缓存一致性协议,即MESI。MESI就是当线程1通过加了lock前缀的总线读取主内存数据到线程的工作内存后,会给这个属性加一个状态E,表示独占状态,这时如果另一个线程也通过总线到主内存读取该属性,复制到该线程的工作内存中,线程1感知到后属性状态就会从E边为S,即从独占状态变成共享状态,另一个线程中该属性的状态也是共享状态。如果两个线程都要修改这个属性的值,会对各自属性所在缓存行加一个锁,向总线发出加锁的消息,总线裁决后胜出的线程修改成功,更改属性状态为M状态,即修改状态,并且通知到其他线程,其他线程就会从S状态改变为I状态,即从共享状态改为无效状态,并且刷新缓存值。这就是MESI缓存一致性协议。 另外为什么说volatile能保证可见性和有序性,但无法保证原子性?因为volatile是对线程的工作内存有效,对寄存器是无效的,有可能寄存器已经读取到当前的属性值,之后属性值才被置为无效,这是刷新缓存值对寄存器也没有作用了,所以volatile保证不了原子性。*/

指令重排的原则happens-before

在这里插入图片描述

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

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

相关文章

kafka基础

文章目录 1、什么是消息队列?2、基础架构3、Kafka为什么快4、零拷贝5、Rebalance机制6、kafka如何避免重复消费7、避免消息丢失8、Kafka怎么实现消息的顺序消费9、什么是ISR10、Kafka文件存储机制 1、什么是消息队列? kafka是一个消息队列的中间件&…

MySQL - 数据库级别的外键

1. 外键 FOREIGN KEY (了解) 测试数据 : 学生表 CREATE TABLE IF NOT EXISTS student (id INT(4) NOT NULL AUTO_INCREMENT COMMENT 学号,name VARCHAR(30) NOT NULL DEFAULT 匿名 COMMENT 姓名,pwd VARCHAR(20) NOT NULL DEFAULT 123456 COMMENT 密码,sex VARC…

FastDFS单机部署及SpringBoot整合

前言 FastDFS是一个开源的高性能分布式文件系统。它的主要功能包括:文件存储、文件同步和文件访问(文件上传和文件下载),可以解决高容量和负载平衡问题。FastDFS应满足其服务基于文件的网站的要求,如照片共享网站和视…

卷积基础知识总结

卷积层是卷积神经网络中的核心模块,**卷积层的目的是提取输入特征图的特征,**如下图所示,卷积核可以提取图像中的边缘信息。卷积也成为过滤器,即Filter 1 卷积的计算方法 卷积运算本质上就是在滤波器和输入数据的局部区域间做点…

ECharts数据可视化

目录 第一章 什么是ECharts 第二章 搭建环境 2.1 Echarts的下载 2.2 Visual Studio Code下载 第三章 一个简单的可视化展示 第四章 Echarts组件 4.1 标题 4.2 提示框 4.3 工具栏 4.4 图例 4.5 时间轴 4.6 数据区域缩放 4.6.1 滑动条型数据区域缩放 4.6.2 内置型…

IDEA中创建编写JSP

一、安装Tmocat并配置环境 安装请参考:https://www.cnblogs.com/weixinyu98/p/9822048.html 安装请参考:https://www.cnblogs.com/zhanlifeng/p/14917777.html 注意:在安装成功Tomcat测试是否成功安装时,访问“http://localhost:8…

MyBatisPlus代码生成器插件

1、下载IDEA插件:MybatisPlus。 2、使用插件生成代码 首先点击IDEA导航菜单上的Other选项,然后进行数据库和代码生成器的配置: 数据库配置: 代码生成器配置,然后点击code generator: 最会插件会按照配置…

VSCode+GDB+Qemu调试ARM64 linux内核

俗话说,工欲善其事 必先利其器。linux kernel是一个非常复杂的系统,初学者会很难入门。 如果有一个方便的调试环境,学习效率至少能有5-10倍的提升。 为了学习linux内核,通常有这两个需要 可以摆脱硬件,方便的编译和…

【MySQL数据库】MySQL 高级SQL 语句二

MySQL 高级 SQL 语句二 一、连接查询1.1 inner join(内连接)1.2 left join (左连接)1.3 right join(右连接) 二、CREATE VIEW ---- 视图三、 UNION - - 连集3.1 UNION3.2 UNION ALL 四、交集值(取两个SQL语句结果的交集…

pwn学习day4——ret2text

文章目录 原理&#xff1a;例子x64x32 原理&#xff1a; 覆盖函数返回地址到程序内存在的gadgets获取shell 例子 #include<stdio.h> #include<stdlib.h>void hint(){system("$0"); } int main(){char buf[0x10];printf("input: ");scanf(&q…

【Java】Java核心 78:Git 教程(1)Git 概述

文章目录 01.GIT概述目标内容小结 02.GIT相关概念目标内容小结 01.GIT概述 Git是一个分布式版本控制系统&#xff0c;常用于协同开发和版本管理的工具。它可以跟踪文件的修改、记录历史版本&#xff0c;并支持多人协同工作。通过Git&#xff0c;你可以轻松地创建和切换分支、合…

【算法题】动态规划中级阶段之跳跃游戏、最大子数组和、解码方法

动态规划中级阶段 前言一、最大子数组和1.1、思路1.2、代码实现 二、跳跃游戏2.1、思路2.2、代码实现 三、解码方法3.1、思路3.2、代码实现 总结 前言 动态规划&#xff08;Dynamic Programming&#xff0c;简称 DP&#xff09;是一种解决多阶段决策过程最优化问题的方法。它是…