缓存行

作者: lenny611 | 来源:发表于2020-10-25 20:05 被阅读0次

在介绍缓存行之前,我们需要先了解操作系统的存储器的层次结构,下图为CSAPP(原书第三版)中存储器层次结构图:


存储器层次结构图

一般的程序执行都是由CPU执行,但是由于CPU与主存的速度差异过大,因此引入了CPU缓存,一般分为三级缓存(至于为什么是三级,不是二级,四级,是因为工业系统长期实际得出的结果,三级缓存为最优):L1,L2,L3,与CPU更接近则访问速度越快。CPU访问缓存的顺序是L1,L2,L3,L1没命中,则去访问L2;L2没命中,则去访问L3,以此类推,一直到命中为止。而在L1,L2,L3中存储的数据并不是以某个变量单独存储的,在每个缓存里面是以缓存行(cache line)为单位存储的(这也是CPU的实现规定的),一般来说一个缓存行的大小在32kb-256kb之间,而通常的缓存行大小则为64kb(同样为工业得出的最优解)。这里带出来一个隐藏的问题就是:多线程修改互相独立的变量且这些变量位于同一个缓存行时,这会影响性能且很难发现,这也被称为伪共享。看以下模拟伪共享代码(即两个变量处于同一个缓存行):

public class CacheLineFalse {
    private static long operationTimes=100000000L;
    private static class T{
        public volatile long data=0L;
    }
    public  static T[] array= new T[2];
    static {
        //分配空间
        array[0]=new T();
        array[1]=new T();
    }
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch=new CountDownLatch(2);
        // 线程1操作array[0].x
         Thread thread1=new Thread(()->{
            for (int i=0;i<operationTimes;i++){
                array[0].data=i;
            }
            latch.countDown();
         });
         //线程2操作array[1].x
        Thread thread2=new Thread(()->{
            for (long i = 0; i < operationTimes; i++) {
                array[1].data=i;
            }
            latch.countDown();
        });
        final long startTime=System.nanoTime();
        thread1.start();
        thread2.start();
        latch.await();
        System.out.println((System.nanoTime()-startTime)/100_0000);
    }
}

执行结果如下:


伪共享执行结果

再来看两个变量处于不同的缓存行:

public class CacheLineTrue {
    private static long operationTimes=100000000L;
    private static class T{
        //一个long占8个字节,8个long类型的刚好满一个缓存行
        private long p1,p2,p3,p4,p5,p6,p7;
        public volatile long data=0L;
        private long p9,p10,p11,p12,p13,p14,p15;
    }
    public  static CacheLineTrue.T[] array= new CacheLineTrue.T[2];
    static {
        //分配空间
        array[0]=new CacheLineTrue.T();
        array[1]=new CacheLineTrue.T();
    }
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch=new CountDownLatch(2);
        // 线程1操作array[0].x
        Thread thread1=new Thread(()->{
            for (int i=0;i<operationTimes;i++){
                array[0].data=i;
            }
            latch.countDown();
        });
        //线程2操作array[1].x
        Thread thread2=new Thread(()->{
            for (long i = 0; i < operationTimes; i++) {
                array[1].data=i;
            }
            latch.countDown();
        });
        final long startTime=System.nanoTime();
        thread1.start();
        thread2.start();
        latch.await();
        System.out.println((System.nanoTime()-startTime)/1000_000);
    }
}

执行结果如下:


处于不同缓存行执行结果

可以看到在时间上还是有差距的,那么来看下两个代码的区别:


区别
为什么多定义了几个long变量,就导致这么大的差距?下面解释下原因:
一个long变量占8个字节,而一个缓存行占64字节,8个long类型的变量刚好充满一个缓存行,而左边这样定义的结果就会导致两个线程访问的data一定不在同一个缓存行内,而右边这样定义会导致两个线程需要重新读取缓存行的内容(假设线程1获得了CPU执行权,volatile的作用会让线程2读取的缓存行失效。当线程2获得了CPU执行权然后执行更新操作,线程1读取的缓存行则会失效),把时间都耗费在这上面,由此产生的时间差,以及带来的性能问题就是这样产生的。

Java8为了避免这种伪共享,实现了字节填充。
JVM参数 -XX:-RestrictContended
@Contended 位于 sun.misc 用于注解java 属性字段,自动填充字节,防止伪共享

相关文章

  • 缓存行

    在介绍缓存行之前,我们需要先了解操作系统的存储器的层次结构,下图为CSAPP(原书第三版)中存储器层次结构图: 一...

  • iOS网络缓存扫盲篇--使用两行代码就能完成80%的缓存需求

    iOS网络缓存扫盲篇--使用两行代码就能完成80%的缓存需求 iOS网络缓存扫盲篇--使用两行代码就能完成80%的...

  • iOS缓存

    简单实用缓存 iOS网络缓存扫盲篇--使用两行代码就能完成80%的缓存需求

  • CAS锁了总线或者缓存行还是volatile锁了总线或者缓存行

    CAS锁了总线或者缓存行还是volatile锁了总线或者缓存行? CAS全称Compare And Set(或Co...

  • 两行代码就能完成80%的缓存需求

    目录 当我们在谈论缓存的时候,我们在谈论什么? GET网络请求缓存 80%的缓存需求:两行代码就可满足 控制缓存的...

  • [转]使用两行代码就能完成80%的缓存需求

    目录 当我们在谈论缓存的时候,我们在谈论什么? GET网络请求缓存 80%的缓存需求:两行代码就可满足 控制缓存的...

  • iOS Cache 数据缓存

    cache里的基本存储单元是cacheline即缓存行,缓存通常分为一级缓存和二级缓存,有些还有三级缓存,通常数据...

  • 使用Redis构建web应用

    登录和cookie缓存 购物车 网页缓存 数据行缓存 网页分析代码格式有问题,见谅 欢迎访问本人博客:http:...

  • JMM - 内存模型

    1,CPU缓存架构 1)cpu缓存架构图image.png2)术语Cache Line:缓存行,又称slot通常6...

  • CPU简介

    基本概念 CPU缓存 & 缓存行 & 缓存一致性: CPU缓存:为了弥补CPU和主存速度上的差异,处理器内部会引入...

网友评论

      本文标题:缓存行

      本文链接:https://www.haomeiwen.com/subject/xvogmktx.html