美文网首页
并发中的伪共享问题

并发中的伪共享问题

作者: 雨山木工 | 来源:发表于2019-03-07 10:08 被阅读5次

    伪共享问题的表现是:并发的修改操作,在CPU的底层实际上是串行的在执行!

    这个涉及到 MESI(缓存一致性协议),参考链接:伪共享问题

    伪共享的原因就是 CPU 在 Invalid 的时候,是会直接废除一行的!

    如果 两个变量 (a,b) 同时在一个 Cache Line 中,处理器A修改了变量a ,那么处理器B中,这个 CacheLine 失效了,这个时候如果处理器B修改了变量b的话,就必须先提交处理器A的缓存,然后处理器B再去主存中读取数据!这样就出现了问题,ab在两个处理器上被修改,本应该是一个并行的操作,但是由于缓存一致性,却成为了串行!这样会严重的影响并发的性能!

    解决方案:

    Java中提供给了我们两种方案:

    填充法Contended 注解

    1. 填充法:就是 扩大对象的大小,这样,就可以一个缓冲行中,只存在一个对象!这样,就不会导致结果是串行执行了!
    public class DataPadding{
        long a1,a2,a3,a4,a5,a6,a7,a8;//防止与前一个对象产生伪共享
        int value;
        long modifyTime;
        long b1,b2,b3,b4,b5,b6,b7,b8;//防止不相关变量伪共享;
        boolean flag;
        long c1,c2,c3,c4,c5,c6,c7,c8;//
        long createTime;
        char key;
        long d1,d2,d3,d4,d5,d6,d7,d8;//防止与下一个对象产生伪共享
    }
    

    上面的代码使用,填充法,对象的属性在内存行中的布局如下

    value , modifyTime


    flag


    createTime
    key

    1. Contended 注解法:Java1.8 中提供了Contended注解,使用这个注解,VM必须设置 -XX:-RestrictContended

    如果在类型上添加Contended注解,那么这个类的对象的每个属性都会在不同的CacheLine

    如果在属性上设置Contended,那么可以指定哪些 属性 处于一个CacheLine

    @SuppressWarnings("restriction")
    public class ContendedGroupData {
        @sun.misc.Contended("group1")
        int value;
        @sun.misc.Contended("group1")
        long modifyTime;
        @sun.misc.Contended("group2")
        boolean flag;
        @sun.misc.Contended("group3")
        long createTime;
        @sun.misc.Contended("group3")
        char key;
    }
    

    这个伪共享的注解,在 LongAddrConcurrentHashMap 中得到了很多的运用,对于并发的修改一个对象中的多个属性的时候,应该防止伪共享!

    相关文章

      网友评论

          本文标题:并发中的伪共享问题

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