安徽建海建设工程有限公司网站,网站空间和域名价格,护栏板官方网站建设,手机怎么创建网页快捷方式目录1.背景简介2.伪共享问题3.问题解决4.JDK使用示例1.背景简介 我们知道#xff0c;CPU 是不能直接访问内存的#xff0c;数据都是从高速缓存中加载到寄存器的#xff0c;高速缓存又有 L1#xff0c;L2#xff0c;L3 等层级。在这里#xff0c;我们先简化这些复杂的层级…
目录1.背景简介2.伪共享问题3.问题解决4.JDK使用示例1.背景简介 我们知道CPU 是不能直接访问内存的数据都是从高速缓存中加载到寄存器的高速缓存又有 L1L2L3 等层级。在这里我们先简化这些复杂的层级关系假设只有一级缓存和一个主内存。 CPU 读取和更新缓存的时候是以行为单位进行的也叫一个 cache line一行一般 64 字节也就是8个long的长度。
2.伪共享问题
一个缓存行可以放多个变量如果多个线程同时访问不同的变量而这些不同的变量又恰好位于同一个缓存行那么会发生什么呢 如上图所示X 和 Y 为相邻 2 个变量位于同一个缓存行两个 CPU core1 和 core2 都加载了它们。
core1 更新 X同时 core2 更新 Y由于数据的读取和更新是以 缓存行 为单位的这就意味着当这2件事同时发生时就产生了竞争导致 core1 和 core2 有可能需要重新刷新自己的数据缓存行被对方更新了最终导致系统的性能大打折扣这就是伪共享问题。
3.问题解决
如下图 如上图所示我们把 X 单独占用一个缓存行Y 单独占用一个缓存行这样各自更新和读取就不会有任何影响了。
对应的操作就是在代码中使用 sun.misc.Contended 注解。
4.JDK使用示例
例如在 JDK1.7 中 Thread 类中为 ThreadLocalRandom 增加的三个成员变量
/*** 线程本地随机的当前种子。*/
sun.misc.Contended(tlr)
long threadLocalRandomSeed;/*** 探测哈希值;如果线程本地随机种子被初始化那么该值也非0。使用缓存填充(注解方式)来避免伪共享。*/
sun.misc.Contended(tlr)
int threadLocalRandomProbe;/*** 从公共线程本地随机序列中分离的二级种子。*/
sun.misc.Contended(tlr)
int threadLocalRandomSecondarySeed;sun.misc.Contended(tlr) 就会在虚拟机层面帮助我们在变量的前后生成一些 padding使得被标注的变量位于同一个缓存行不与其他变量冲突。
在 Thread 对象中threadLocalRandomSeed、threadLocalRandomSeed、threadLocalRandomSecondarySeed 被标记为同一组 tlr使得这 3 个变量放置于一个单独的缓存行而不与其它变量发生冲突从而提高在并发环境中的访问速度。
整理完毕完结撒花~