theme: channing-cyan
这是我参与更文挑战的第25天,活动详情查看: 更文挑战。
紧接着上一篇你好,请谈谈volatile关键字?(一)
四、从硬件层面分析可见性
volatile
核心诠释的是可见性
,那么这个可见性
的本质的是什么呢,我们从硬件层面细细分析。
我们知道,CPU
、内存
、I/O设备
等是计算机的核心组件。硬件产商会通过不断提高这三个组件性能来提升计算机的整体性能。这三者在在处理速度上差异很大,CPU
>内存
>I/O设备
。根据木桶原理,影响整体性能最重要的因素是最短板。为了平衡三者的性能,达到最大效率利用计算资源,前面的文章《并发编程之进程、线程、协程》有讲到聪慧的一群人研究出了操作系统、进程、线程通过时间片切换最大化的利用CPU
的资源。
但,这还不够,有没有一种可能CPU
执行指令的时候,访问的资源是直接存储在CPU
上的,而不是去访问内存,当然有的,那就是CPU
高速缓存, 在高速缓存之后,为了更加合理的利用高速缓存,人们又对编译器的指令进行了优化。虽然实实切切的不断榨干了CPU
资源,但正因为这些优化,也带了各种各样的问题。勤劳的人们又开始解决这样问题,将并发编程思想带入了井喷时代。
4.1 CPU高速缓存
CPU
高速缓存是是位于CPU和内存之间的临时存储器,它的作用主要是为了解决CPU运算速度与内存读写速度不匹配的矛盾。更直白的说我们使用计算机最终使用到的是计算机的计算能力,但是完成计算这件事情,是很复杂的,不仅仅有CPU参与就行了,CPU需要和内存交互进行读取、写入操作。所以为了尽可能消除在CPU执行过程中对这种IO的耗时,人们便研究出高速缓存来解决这样的问题。
如图,
L1 Cache
指的是一级缓存,主要是缓存指令和缓存数据,Core
独享。因为其结构相当的复杂,造价成本高,所以其在高速缓存中容量最小,普遍容量范围为32KB~512KB。L2 Cache
指的是二级缓存,直接影响CPU
性能,Core
独享。普遍容量范围为128KB~24MB。L3 Cache
指的是三级缓存,它的作用是进一步降低内存的延迟,提升数据更多场景计算时的性能,Core
共享。普遍容量范围为2MB~32MB。
总的来说,越接近CPU
核心的缓存,容量就越小,同时访问延迟就越低 (速度越快)。
通过高速缓存的存储交互很好的解决了处理器与内存速度的差异性矛盾,但它有引入一个新的难题,那就是缓存一致性。
4.2 缓存一致性
一个运算的过程是,运算开始时将运算要使用到的数据移动到缓存中,当运算结束时再将运算结果同步到内存中。 这个最大的问题是在多核CPU
运行环境下,主存上的共享数据可能会被多个核同时缓存,同时进行读写操作,写回的数据第一时间是放在高速缓存中,然后再进一步同步到主存中,但其它的核心的缓存可能感知不到变化,这样就会产生缓存不一致的问题。
为了解决这个问题,保证缓存一致性,可以采取两种方式解决。
- 总线锁
- 缓存锁
总线锁,简单点说,在总线层面,局部锁定CPU和内存之间的通信,在锁定期间,其它线程不能访问锁定的内存地址。这种方式开销很大,影响面广,锁控制的粒度粗了,不太适合解决缓存不一致的问题。
所以为了优化总线锁,大佬们又提出了缓存锁。这个缓存锁的核心机制就是缓存一致性协议,这个协议,降低了锁的粒度,同时对于主存上同一份共享数据,保证了CPU
每个核上缓存的内容是一致的。
4.3 CPU Cache 与 Cache Line
上面讲到使用缓存一致性协议的缓存锁,能保证缓存一致。这种协议有很多,最为常见的是MESI
。 因为MESI
协议在缓存中实现是每个Cache line
的4个状态,讲协议之前,有一个硬件的知识需提前说一下,那就是CPU Cache
和Cahce Line
的区别。
Cache Line
可以理解为CPU Cache
中的最小缓存单位,在主流的CPU Cache
中,一般大小为64KB,也就是说如果L1 Cache
的大小为512KB,那么此Cache 一共有8个(512/64=8)Cache Line
,具体参照下图示意。所以MESI
产生效用的粒度是Cache Line
,这样最好的作用,当发生主存的数据和高速缓存的数据需要同步的时候,影响的程度只是在Cache Line
,而不至于要操作整个CPU Cache
。
篇幅较长,继续阅读请点击【面时莫慌】你好,请谈谈volatile关键字?(三)
哥佬倌,莫慌到走!觉好留个赞,探讨上评论。欢迎关注面试专栏面时莫慌 | Java并发编程,面试加薪不用愁。也欢迎关注我,一定做一个长更的好男人。