java并发编程(三)cpu cache & 缓存一致性
一 cpu cache
1. cache的意义
为什么需要CPU cache?因为CPU的频率太快了,快到主存跟不上,这样在处理器时钟周期内,CPU常常需要等待主存,浪费资源。所以cache的出现,是为了缓解CPU和内存之间速度的不匹配问题(结构:cpu -> cache -> memory)。
CPU cache有什么意义?cache的容量远远小于主存,因此出现cache miss在所难免,既然cache不能包含CPU所需要的所有数据,那么cache的存在真的有意义吗?当然是有意义的——局部性原理
- 时间局部性:如果某个数据被访问,那么在不久的将来它很可能被再次访问
- 空间局部性:如果某个数据被访问,那么与它相邻的数据很快也可能被访问
2. cache和寄存器
存储器的三个性能指标——速度、容量和每位价格——导致了计算机组成中存储器的多级层次结构,其中主要是缓存和主存、主存和磁盘的结构。那么在主存之上,cache和寄存器之间的关系是?

举个例子,当你在思考一个问题的时候,寄存器存放的是你当前正在思考的内容,cache存放的是与该问题相关的记忆,主存则存放无论与该问题是否有关的所有记忆,所以,寄存器存放的是当前CPU执行的数据,而cache则缓存与该数据相关的部分数据,因此只要保证了cache的一致性,那么寄存器拿到的数据也必然具备一致性
3、CPU cache结构
- 单核CPU cache结构

在单核CPU结构中,为了缓解CPU指令流水中cycle冲突,L1分成了指令(L1P)和数据(L1D)两部分,而L2则是指令和数据共存
- 多核CPU cache结构

多核CPU的结构与单核相似,但是多了所有CPU共享的L3三级缓存。在多核CPU的结构中,L1和L2是CPU私有的,L3则是所有CPU核心共享的。
二 缓存一致性 & MESI协议
1、什么是缓存一致性
用于保证多个CPU cache之间缓存共享数据的一致
2. cache的写方式
- write through(写通):每次CPU修改了cache中的内容,立即更新到内存,也就意味着每次CPU写共享数据,都会导致总线事务,因此这种方式常常会引起总线事务的竞争,高一致性,但是效率非常低
- write back(写回):每次CPU修改了cache中的数据,不会立即更新到内存,而是等到cache line在某一个必须或合适的时机才会更新到内存中
无论是写通还是写回,在多线程环境下都需要处理缓存cache一致性问题。为了保证缓存一致性,处理器又提供了写失效(write invalidate)和写更新(write update)两个操作来保证cache一致性。
- 写失效:当一个CPU修改了数据,如果其他CPU有该数据,则通知其为无效
- 写更新:当一个CPU修改了数据,如果其他CPU有该数据,则通知其跟新数据
写更新会导致大量的更新操作,因此在MESI协议中,采取的是写失效(即MESI中的I:ivalid,如果采用的是写更新,那么就不是MESI协议了,而是MESU协议)
3. cache line

cache line是cache与内存数据交换的最小单位,根据操作系统一般是32byte或64byte。在MESI协议中,状态可以是M、E、S、I,地址则是cache line中映射的内存地址,数据则是从内存中读取的数据
工作方式:当CPU从cache中读取数据的时候,会比较地址是否相同,如果相同则检查cache line的状态,再决定该数据是否有效,无效则从主存中获取数据,发起一次RR(remote read)
工作效率:当CPU能够从cache中拿到有效数据的时候,消耗几个CPU cycle,如果发生cache miss,则会消耗几十上百个CPU cycle
3. 状态介绍
MESI协议将cache line的状态分成以下四种
- modify(修改):当前CPU cache拥有最新数据(最新的cache line),其他CPU拥有失效数据(cache line的状态是invalid),虽然当前CPU中的数据和主存是不一致的,但是以当前CPU的数据为准
- exclusive(独占):只有当前CPU中有数据,其他CPU中没有改数据,当前CPU的数据和主存中的数据是一致的
- shared(共享):当前CPU和其他CPU中都有共同数据,并且和主存中的数据一致
- invalid(失效):当前CPU中的数据失效,数据应该从主存中获取,其他CPU中可能有数据也可能无数据,当前CPU中的数据和主存被认为是不一致的,在MESI协议中采取的是写失效(write invalidate)
4. cache操作
MESI协议中,每个cache的控制器不仅知道自己的操作(local read和local write),通过监听也知道其他CPU中cache的操作(remote read和remote write)。对于自己本地缓存有的数据,CPU仅需要发起local操作,否则发起remote操作,从主存中读取数据,cache控制器通过总线监听,仅能够知道其他CPU发起的remote操作,但是如果local操作会导致数据不一致性,cache控制器会通知其他CPU的cache控制器修改状态
- local read(LR):读本地cache中的数据
- local write(LW):将数据写到本地cache
- remote read(RR):读取内存中的数据
- remote write(RW):将数据写通到主存
java并发编程(三)cpu cache & 缓存一致性的更多相关文章
- Java并发编程三个性质:原子性、可见性、有序性
并发编程 并发程序要正确地执行,必须要保证其具备原子性.可见性以及有序性:只要有一个没有被保证,就有可能会导致程序运行不正确 线程不安全在编译.测试甚至上线使用时,并不一定能发现,因为受到当时的 ...
- 【Java并发编程三】闭锁
1.什么是闭锁? 闭锁(latch)是一种Synchronizer(Synchronizer:是一个对象,它根据本身的状态调节线程的控制流.常见类型的Synchronizer包括信号量.关卡和闭锁). ...
- Java并发编程 (三) 项目准备
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.案例环境初始化 1.环境搭建与准备 Spring Boot 项目,https://start.spr ...
- Java 并发编程(三):如何保证共享变量的可见性?
上一篇,我们谈了谈如何通过同步来保证共享变量的原子性(一个操作或者多个操作要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行),本篇我们来谈一谈如何保证共享变量的可见性(多个线程访问同一个变 ...
- Java并发编程(三):ReentrantLock
ReentrantLock是可以用来代替synchronized的.ReentrantLock比synchronized更加灵活,功能上面更加丰富,性能方面自synchronized优化后两者性能没有 ...
- 【Java并发编程】从CPU缓存模型到JMM来理解volatile关键字
目录 并发编程三大特性 原子性 可见性 有序性 CPU缓存模型是什么 高速缓存为何出现? 缓存一致性问题 如何解决缓存不一致 JMM内存模型是什么 JMM的规定 Java对三大特性的保证 原子性 可见 ...
- 基于JVM原理、JMM模型和CPU缓存模型深入理解Java并发编程
许多以Java多线程开发为主题的技术书籍,都会把对Java虚拟机和Java内存模型的讲解,作为讲授Java并发编程开发的主要内容,有的还深入到计算机系统的内存.CPU.缓存等予以说明.实际上,在实际的 ...
- [Java并发编程(三)] Java volatile 关键字介绍
[Java并发编程(三)] Java volatile 关键字介绍 摘要 Java volatile 关键字是用来标记 Java 变量,并表示变量 "存储于主内存中" .更准确的说 ...
- Java并发编程里的volatile。Java内存模型核CPU内存架构的对应关系
CPU内存架构:https://www.jianshu.com/p/3d1eb589b48e Java内存模型:https://www.jianshu.com/p/27a9003c33f4 多线程下的 ...
随机推荐
- 连接池未注册org.logicalcobwebs.proxool.ProxoolException: Attempt to refer to a unregistered pool by its alias 'XXX'
代码之前一直好好的,写了一个定时器后报错,本地测试为了立马能执行就用cron表达式* * * * * ?,为了只执行一次在最后面加上Thread.sleep(1000*3600*24)睡眠二十四小时从 ...
- vue-cli项目中使用vw——相比flexible更原生的移动端解决方案
安装命令行输入: yarn add postcss-px-to-viewport 或 npm i postcss-px-to-viewport -save -dev 配置package.json中,在 ...
- elementUi vue el-radio 监听选中变化
//change是radio-group标签的事件 <div> <el-radio-group v-model="radioSex" @change=" ...
- QT之Qt之Q_PROPERTY宏理解
在初学Qt的过程中,时不时地要通过F2快捷键来查看QT类的定义,发现类定义中有许多Q_PROPERTY的东西,比如最常用的QWidget的类定义: Qt中的Q_PROPERTY宏在Qt中是很常用的,那 ...
- Python数据分析 之时间序列基础
1. 时间序列基础 import numpy as np import pandas as pd np.random.seed(12345) import matplotlib.pyplot as p ...
- Spring Cloud Sleuth 整合
引入Maven依赖 org.springframework.cloud spring-cloud-starter-sleuth 日志发生的变化 当应用ClassPath下存在org.springfre ...
- Python人工智能常用库Numpy使用入门
第一章 jupyter notebook简单教程 命令模式按键esc开启 Enter : 转入编辑模式 Shift-Enter : 运行本单元,选中下个单元 Ctrl-Enter : 运行本单元 Al ...
- 面试题:什么叫B树
B是balanced的意思 是在二叉查找树 树的基础上增加了平衡的性质 导致它不是 二叉树了,变成了多叉树,但是叉几路又有了限制 否则怎么平衡呢 一棵m阶B树(balanced tree o ...
- Miniconda
什么是conda conda的基本使用方式 conda是一个开源包管理系统和环境管理系统,用于安装多个版本的软件包及其依赖关系,并在它们之间轻松切换. 它适用于Linux,OS X和Windows,是 ...
- 百度云人脸识别API人脸库管理
from urllib import request import base64 import requests import re import json import urllib impor ...