(点击
上方公众号
,可快速关注)
来源:Float_Luuu,
my.oschina.net/andylucc/blog/539783
如有好文章投稿,请点击 → 这里了解详情
今天查了很多资料,主要是想搞清楚写JAVA和CacheLine有什么关系以及我们如何针对CacheLine写出更好的JAVA程序。
CPU和内存
CPU是计算机的大脑,它负责运算,内存是数据,它为CPU提供数据。这里之所以忽略其他存储设备是为了简化模型。假设我们面对的是具有两个核心的CPU,那么我们的模型大概如下面的样子:
CPU计算核心不会直接和内存打交道,它会直接从缓存拿数据,如果缓存没拿到,专业点说即缓存未命中的时候才会去内存去拿,同时会更新缓存。这个过程CPU不会仅仅读取需要的某个字节或字的内容,而会按策略读取一块内容。典型的处理器策略是向前进的方向读取小于2048字节的数据。如上图所示,L1缓存(一级缓存)离CPU内核最近,容量也最小同时造价也最高,属于内核独立使用。L2缓存离得远些,容量比L1大写但是还是属于独立的内核使用。L3缓存离的最远,也是最慢的缓存,这层缓存为所有内核共享。
缓存行
上面一节我们介绍了CPU和内存之间的模型,本节介绍下缓存行。CPU从缓存中读取内容并不是一个字节或一个字读的,而是一行一行,也可以理解为一块一块读的。CPU是这样设计的,我们想想,相邻数据的相关性往往很大,这么设计可以提高缓存的命中率,也降低访问缓存的次数。上面提到的一行叫做缓存行。典型的大小是32-256字节,其中最常见的是64字节。这是缓存一致性的最小粒度,如果一行中有一个字节哪怕一个位的内容内修改并写回内存,那么其他内核的该缓存行将会被标志位无效。假设两个内核正在执行不同的线程,并且操作同一个缓存行,A线程修改了缓存行的第一个字节,B线程需要访问第二个字节,这个时候该缓存行其实已经被进行了一次和内存同步的操作,保证该段和内存中该行数据一致,然而这个过程B线程访问的这个字节和第一个线程访问的字节并没有关系。这个时候有同学有疑问了,那么如果两个内核的线程同时对该段进行操作,也就是没有谁先谁后的情况,会出现什么情况呢。其实这里涉及到另外一个概念,叫缓存一致性协议(Cache Coherency)。即我们已经有了一个保证:在任意时刻,任意级别的缓存段中的内容,等同于它对应的内存中的内容。