cpu缓存

MESI协议:Cache 一致性协议

左心房为你撑大大i 提交于 2019-12-12 12:48:01
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 总线嗅探机制 把所有的读写请求都通过总线( Bus )广播给所有的 CPU 核心,然后让各个核心去“嗅探”这些请求,再根据本地的情况进行响应。 MESI 协议 基于 写失效 ( Write Invalidate ) 如果某个 CPU 核心 写入一个 Cache Line,则会广播一个 失效 请求告诉所有其他的 CPU 核心。 Cache Line 的 标记 M:代表已修改( Modified ) 缓存行是脏的( dirty ),与主存的值不同。如果别的CPU内核要读主存这块数据,该缓存行必须回写到主存,状态变为共享( S ). E:代表独占( Exclusive ) 缓存行只在当前缓存中,但是干净的( clean )--缓存数据同于主存数据。当别的缓存读取它时,状态变为共享( S );当前写数据时,变为已修改( M )状态。 S:代表共享( Shared ) 缓存行也存在于其它缓存中且是干净( clean )的。缓存行可以在任意时刻抛弃。 I:代表已失效( Invalidated ) 缓存行是脏的(dirty),无效的。 任意一对缓存,对应缓存行的相容关系: 比如: 当块标记为 M (已修改), 在其他缓存中的数据副本被标记为 I (无效). 参考: https://zh.wikipedia.org/wiki

zz《可伸缩服务架构 框架与中间件》综合

女生的网名这么多〃 提交于 2019-12-10 18:09:59
=======开篇吐槽:最近一段时间刚好碰上中秋国庆双节,而且工作任务繁重,基本很难保证有时间来写文章了======= 《可伸缩服务架构 框架与中间件》与《分布式服务架构 原理、设计与实战》是要配套捆绑着看,这营销手段,服。 这书主要介绍了在分布式系统中常规用到的一些框架组件,比如分布式ID、消息队列、缓存、RPC框架、ES等。书中大部分内容的作用更多的是整体介绍、知识点扩展、初步入门,书中贴的源代码其中很难让人认真一行一行去阅读学习。想要更深入的学习,需要在平时工作多积累丰富的项目经验,或者多看看开源项目,从而去总结和提取。 每一章介绍一个组件,摘抄一些自己觉得有用的内容,归纳整理,然后加以理解。(主要还是强迫自己形成总结成文的习惯,看的书很多,都总是很容易忘记,效果甚微) 第1章 如何设计一款永不重复的高性能分布式发号器 1. 为什么不直接采用UUID? 虽然UUID能够保证唯一性,但无法满足业务系统需要的很多其他特性,比如时间粗略有序性、可反解和可制造性(说人话,就是分布式ID需要体现根据时间递增的特点,并且从ID串中能解析出一定的业务含义),同时UUID比较长,占空间大,性能较差。 2. 那基于数据库来实现呢? 即通过调整自增字段或者数据库sequence的步长来确保跨数据库的ID的唯一性,但这种方案强依赖于数据库。 实现方案,可见我:重构 - 分布式ID设计方案 3.

两重for循环的效率对比

試著忘記壹切 提交于 2019-12-09 04:55:11
int a[n][m] for ( int i= 0 ;i<n;i++){ for ( int j= 0 ;j<m;j++){ // a[i][j] } } for ( int j= 0 ;j<m;j++){ for ( int i= 0 ;i<n;i++){ // a[i][j] } } 以上两个循环的效率谁比较高: 对于现代数组来说,都是行存储优先: a[ 0 ][ 0 ] a[ 0 ][ 1 ] a[ 0 ][ 2 ] .... a[ 100 ][ 0 ] a[ 100 ][ 1 ] .... a[ n ][ m ] 而我们的缓存,主要是将内存中的某段数据放入缓存区,下次访问内存则不需通过内存读取而是直接从缓存读取。 比如一个通用CPU,一级缓存(L1-Cache)的大小为16K,而其组织结构为每32个字节一组,我们能一次缓存8个整形数据: a[ 0 ][ 0 ] a[ 0 ][ 1 ] a[ 0 ][ 2 ] a[ 0 ][ 3 ] 如果我们以先列后行的形式进行访问的话: a[ 0 ][ 0 ]命中 a[ 1 ][ 0 ]不命中,重新读取内存数据至缓存 a[ 2 ][ 0 ]不命中,重新读取内存数据至缓存 ... 以此类推,这种读取的方法不仅仅降低了缓存的命中率,而且还增加了大量的读取内存的时间开销。 相反以先行后列地读取: a[ 0 ][ 0 ]命中 a[ 0 ][ 1

java 缓存

独自空忆成欢 提交于 2019-12-06 13:04:29
外存:   也就是我们经常说的(CDEF盘的大小)外储存器是指除计算机内存及CPU缓存以外的储存器,此类储存器一般断电后仍然能保存数据。常见的外存储器有硬盘、软盘、光盘、U盘等,一般的软件都是安装在外存中 内存:   内存是计算机中重要的部件之一,它是与CPU进行沟通的桥梁。计算机中所有程序的运行都是在内存中进行的,因此内存的性能对计算机的影响非常大。内存(Memory)也被称为内存储器,其作用是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。只要计算机在运行中,CPU就会把需要运算的数据调到内存中进行运算,当运算完成后CPU再将结果传送出来,内存的运行也决定了计算机的稳定运行,此类储存器一般断电后数据就会被清空 高速缓存:   高速缓存是用来协调CPU与主存之间存取速度的差异而设置的。一般情况下,CPU的工作速度高,但内存的工作速度相对较低,为了解决这个问题,通常使用高速缓存,高速缓存的存取速度介于CPU和主存之间。系统将一些CPU在近几个时间段经常访问的内容存入高速缓冲,当CPU需要使用数据时,先在高速缓存中找,如果找到,就不必访问内存了,找不到时,再找内存,这样就在一定程度上缓解了由于主存速度低造成的CPU“停工待料”的情况 -------------------------------------------------------------------

Java并发编程 (二) 并发基础

杀马特。学长 韩版系。学妹 提交于 2019-12-06 10:51:54
一、CPU多级缓存-缓存一致性 1、CPU多级缓存 ​ 上图展示的是CPU高级缓存的配置,数据的读取和存储都经过高速缓存,CPU核心与高速缓存之间有一条特殊的快速通道;在这个简化的图中,主存和缓存都连接在系统总线上,这条总线同时还用于其他组件的通信。 ​ 高速缓存出现后不久,系统变得更加复杂,高速缓存和主存之间的速度差异被拉大,直到加入L1d(又叫一级缓存)的缓存,新加入的这一个缓存比高速缓存更大,但是更慢,由于加大一级缓存的做法从经济上是行不通的。所以有了二级缓存。甚至,现在有些系统有了三级缓存。 2、CPU cache: 为什么需要CPU cache? CPU的频率太快了,快到主存跟不上,这样在处理器时钟周期内,CPU常常需要等待主存,浪费资源。所以cache的出现,是为了缓解CPU和内存之间速度的不匹配问题(结构: CPU -> cache - >memory ). CPU cache 有什么意义? 1)时间局部性: 如果某个数据被访问,那么在不久的将来它很可能被再次访问; 2)空间局部性: 如果某个数据被访问,那么与它相邻的数据很快也可能被访问; 3、CPU多级缓存 - 缓存一致性(MESI) 用于保证多个CPU cache之间缓存共享数据的一致 ​ M 代表modify,表示被修改;指的是该缓存行只被缓存在该CPU的缓存中,并且是被修改过的,因此

全面理解Java内存模型

不羁岁月 提交于 2019-12-06 10:44:53
------------恢复内容开始------------ 1. java内存模型即java Memory Model,简称JMM.JMM定义了Java虚拟机(JVM)在计算机内存(RAM)中的工作方式。JVM是整个计算机虚拟模型,所以JMM是隶属于JVM的。 2.并发编程有两个关键问题: 线程之间的通信和同步 。 3.线程之间的 通信 机制有两种: 共享内存和消息传递 。 1)在 共享内存 的并发模型里,线程之间共享程序的公共状态,线程之间通过写读内存中的公共状态来 隐式 进行通信,典型的共享内存通信方式就是通过共享对象进行通信。 2)在 消息传递 的并发模型里,线程之间没有公共状态,线程之间必须通过明确的发送消息来 显式 进行通信,在Java中典型的消息传递方式是wait()和notify() 4.线程之间的 同步 是指程序用于控制不同线程之间操作发生相对顺序的机制。 1)在 共享内存 并发模型里,同步是 显式 进行的。必须显式指定某个方法或某段代码需要在线程之间互斥执行。 2)在 消息传递 的并发模型里,由于消息的发送必须在消息的接收之前,因此同步是 隐式 进行的。 5.Java的并发采用的是 共享内存模型 ,即Java内存模型(简称JMM), JMM决定一个线程对共享变量的写入合适对另一个线程可见 。从抽象的角度来看, JMM定义了线程和主内存之间的抽象关系

什么是缓存

淺唱寂寞╮ 提交于 2019-12-06 07:44:06
缓存简单理解就是保存的一个数据副本,以便于后续能够进行快速的访问。 缓存的使用是为了解决快速访问数据(读数据)的场景。在现有的互联网应用中,缓存的使用是一种能够提升服务快速响应的关键技术,需要在设计技术方案时对业务场景,具有一定的前瞻性评估后,决定在技术架构中是否需要引入缓存解决这种这种非功能需求。 缓存在计算机领域中实际案例存在很多,比如CPU的缓存是为了解决CPU的运算速度和内存的读取数据不平衡的问题,CPU的运算速度远快与内存的读写速度,为了降低CPU等待数据读写的时间,在CPU中引入L1/L2/L3多级缓存。 再比如Linux中的文件缓存,实际上我们在编程时,会谈论到数据的内存地址,但是我们接触的都是虚拟地址而不是真实的物理地址,计算机中的内存管理单元(MMU)和页表会将虚拟地址转换成物理地址。在计算机硬件领域中就已有很多关于缓存的应用案例,实际上在软件架构中关于缓存的设计会借鉴于很多传统且成熟的计算机硬件缓存设计的思想。 来源: https://www.cnblogs.com/doit8791/p/11968725.html

Spring Cache使用

瘦欲@ 提交于 2019-12-06 03:44:39
记录下自己项目在用的Spring Cache的使用方式。 Spring的抽象已经做得够好了,适合于大多数场景,非常复杂的就需要自己AOP实现了。 Spring官网的文档挺不错的,但是对Cache这块的介绍不是很详细,结合网上大牛的博文,汇总下文。 缓存概念 缓存简介 缓存,我的理解是:让数据更接近于使用者;工作机制是:先从缓存中读取数据,如果没有再从慢速设备上读取实际数据(数据也会存入缓存);缓存什么:那些经常读取且不经常修改的数据/那些昂贵(CPU/IO)的且对于相同的请求有相同的计算结果的数据。如CPU–L1/L2–内存–磁盘就是一个典型的例子,CPU需要数据时先从L1/L2中读取,如果没有到内存中找,如果还没有会到磁盘上找。还有如用过Maven的朋友都应该知道,我们找依赖的时候,先从本机仓库找,再从本地服务器仓库找,最后到远程仓库服务器找;还有如京东的物流为什么那么快?他们在各个地都有分仓库,如果该仓库有货物那么送货的速度是非常快的。 缓存命中率 即从缓存中读取数据的次数 与 总读取次数的比率,命中率越高越好: 命中率 = 从缓存中读取次数 / (总读取次数[从缓存中读取次数 + 从慢速设备上读取的次数]) Miss率 = 没有从缓存中读取的次数 / (总读取次数[从缓存中读取次数 + 从慢速设备上读取的次数]) 这是一个非常重要的监控指标

volatile关键字的作用是什么?

▼魔方 西西 提交于 2019-12-06 01:56:13
Java 中 volatile 关键字是一个类型修饰符。JDK 1.5 之后,对其语义进行了增强。 保证了不同线程对共享变量进行操作时的可见性,即一个线程修改了共享变量的值,共享变量修改后的值对其他线程立即可见 通过禁止编译器、CPU 指令重排序和部分 happens-before 规则,解决有序性问题 volatile 可见性的实现 在生成汇编代码指令时会在 volatile 修饰的共享变量进行写操作的时候会多出 Lock 前缀的指令 Lock 前缀的指令会引起 CPU 缓存写回内存 一个 CPU 的缓存回写到内存会导致其他 CPU 缓存了该内存地址的数据无效 volatile 变量通过缓存一致性协议保证每个线程获得最新值 缓存一致性协议保证每个 CPU 通过嗅探在总线上传播的数据来检查自己缓存的值是不是修改 当 CPU 发现自己缓存行对应的内存地址被修改,会将当前 CPU 的缓存行设置成无效状态,重新从内存中把数据读到 CPU 缓存 看一下我们之前的一个可见性问题的测试例子 package constxiong.concurrency.a014; /** * 测试可见性问题 * @author ConstXiong */ public class TestVisibility { //是否停止 变量 private static boolean stop = false;

CAS 的原理

浪子不回头ぞ 提交于 2019-12-05 21:02:27
什么是CAS CAS (compareAndSwap),中文叫比较交换,一种无锁原子算法。过程是这样:它包含 3 个参数 CAS(V,E,N),V表示要更新变量的值,E表示预期值,N表示新值。仅当 V值等于E值时,才会将V的值设为N,如果V值和E值不同,则说明已经有其他线程做两个更新,则当前线程则什么都不做。最后,CAS 返回当前V的真实值。CAS 操作时抱着乐观的态度进行的,它总是认为自己可以成功完成操作。 CAS的全称为Compare And Swap,直译就是比较交换。是一条CPU的原子指令,其作用是让CPU先进行比较两个值是否相等,然后原子地更新某个位置的值,其实现方式是基于硬件平台的汇编指令,在intel的CPU中,使用的是 cmpxchg 指令,就是说CAS是靠硬件实现的,从而在硬件层面提升效率。 当多个线程同时使用CAS 操作一个变量时,只有一个会胜出,并成功更新,其余均会失败。失败的线程不会挂起,仅是被告知失败,并且允许再次尝试,当然也允许实现的线程放弃操作。基于这样的原理,CAS 操作即使没有锁,也可以发现其他线程对当前线程的干扰。 与锁相比,使用CAS会使程序看起来更加复杂一些,但由于其非阻塞的,它对死锁问题天生免疫,并且,线程间的相互影响也非常小。更为重要的是,使用无锁的方式完全没有锁竞争带来的系统开销,也没有线程间频繁调度带来的开销,因此