加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

为什么java的Exchanger.Slot缓存行填充像这样?

发布时间:2020-12-15 02:13:20 所属栏目:Java 来源:网络整理
导读:当我在 java中阅读’虚假共享’机制时,我在java.util.concurrent.Exchanger.Slot中找到以下代码 /** * A Slot is an AtomicReference with heuristic padding to lessen * cache effects of this heavily CAS'ed location. While the * padding adds noticea
当我在 java中阅读’虚假共享’机制时,我在java.util.concurrent.Exchanger.Slot中找到以下代码

/**
 * A Slot is an AtomicReference with heuristic padding to lessen
 * cache effects of this heavily CAS'ed location.  While the
 * padding adds noticeable space,all slots are created only on
 * demand,and there will be more than one of them only when it
 * would improve throughput more than enough to outweigh using
 * extra space.
 */
private static final class Slot extends AtomicReference<Object> {
    // Improve likelihood of isolation on <= 64 byte cache lines
    long q0,q1,q2,q3,q4,q5,q6,q7,q8,q9,qa,qb,qc,qd,qe;
}

这很奇怪.为什么长数是15(q0-qe),
所以我可以计算出对象的大小应该是:
15 * 8(长)8(父值的长值)16(64位jvm的对象头指针)= 144字节.
要么:
15 * 8(长)8(父的长值)8(32位jvm的对象头指针)= 136字节.
当我读到Disruptor’s implemention:时

public long p1,p2,p3,p4,p5,p6,p7; // cache line padding

private volatile long cursor = INITIAL_CURSOR_VALUE;

public long p8,p9,p10,p11,p12,p13,p14; // cache line padding

大小应为7 * 8 8 7 * 8 8(对象头操作大小为32位jvm)= 128 = 64 * 2.
由于大多数cpu的默认缓存行大小为64字节,因此discruptor的impl可以避免’False sharing’.
所以我的问题是在课堂上填充的数量
java.util.concurrent.Exchanger.Slot是对还是错?

解决方法

java.util.concurrent.Exchanger.Slot中的填充正在安全地播放.它正在添加额外的填充,而另一方面,破坏者正在添加足够的.

如果JVM重新排序字段并且高速缓存行大小为128位,则破坏程序方法也可能失败.最安全的方法是通过继承来分隔字段:

class MemoryFieldAddress {
    private long address;

    public final long getAddress() {
        return address;
    }

    protected final void setAddress(final long address) {
        this.address = address;
    }
}

class MemoryAddressPad1 extends MemoryFieldAddress {
    long p1_1,p1_2,p1_3,p1_4,p1_5,p1_6,p1_7,p1_8,p1_9,p1_10,p1_11,p1_12,p1_13,p1_14,p1_15,p1_16,p1_17;
}

class MemoryFieldBytes extends MemoryAddressPad1 {
    private long bytes;

    public final long getBytes() {
        return bytes;
    }

    protected final void setBytes(final long bytes) {
        this.bytes = bytes;
    }
}

class MemoryAddressPad2 extends MemoryFieldBytes {
    long p2_1,p2_2,p2_3,p2_4,p2_5,p2_6,p2_7,p2_8,p2_9,p2_10,p2_11,p2_12,p2_13,p2_14,p2_15,p2_16,p2_17;
}

// Finally the full implimentation
public class Memory extends MemoryAddressPad2 {}

如果需要,您可以计算最终字段,很少更新字段朝向填充.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读