首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么java的Exchanger.Slot缓存行填充像这样?

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

Stack Overflow用户
提问于 2016-02-24 15:14:42
回答 2查看 623关注 0票数 4

当我在java中阅读“错误共享”机制时,我在java.util.concurrent.Exchanger.Slot中找到了以下代码

代码语言:javascript
复制
    /**
 * 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;
}

它是strange.Why,长的个数是15 (q0 - qe),所以我可以计算对象的大小应该是:

15 *8 ( long ) +8(父级长值)+ 16 ( 64位jvm上的对象头指针)=144个字节。

或者:

15 *8 ( long ) +8(父级长值)+ 8 ( 32位jvm上的对象头指针)=136个字节。

当我读干扰者的实施:的时候

代码语言:javascript
复制
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可以避免“错误共享”。

那么,我的问题是,班里的垫长是多少,java.util.concurrent.Exchanger.Slot是对还是错?

EN

回答 2

Stack Overflow用户

发布于 2016-09-16 09:15:01

java.util.concurrent.Exchanger.Slot中的填充物是安全的。它是增加额外的填充,而另一方面,破坏是刚刚增加的。

此外,如果JVM重新排序字段,而缓存行大小为128位,则干扰器方法可能会失败。最安全的方法是通过继承分隔字段:

代码语言:javascript
复制
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 {}

如果需要,可以将最终字段和很少更新的字段计算为填充字段。

票数 0
EN

Stack Overflow用户

发布于 2018-04-11 06:25:38

为了回答您的问题,您需要知道java obj的结构,在默认情况下,java按长/双、int、oops、.等顺序排列obj字段。例如:您看到的如下所示:

代码语言:javascript
复制
public class testObj{
    int a,b,c;
    Object obj1;
    Object obj2;
    short s1,s2;
    long  l1,l2;
}

但实际上,安排如下

代码语言:javascript
复制
    public class testObj{

    long l1,l2;
    int a,b,c;
    short s1,s2
    Object 1
    Object 2
}

这意味着长字段q1.......qe将安排在java obj的开头,这意味着它至少可以在要保护的字段之前填充缓存行,对于其余的对象,它们至少可以占用缓存行的其余部分。

  1. 背景色1-+
  2. 缓存第2行++++++++++ X(要保护的字段)*
  3. 缓存第3行*

(X)指您要保护的字段

(+)指填充长字段的120个字节

(*)指讣告的其余部分

对于您的情况,它是一个数组,它是连续的,所以它将是

生产线: xxxxxxxx 背景色: xxxxxxx array1xx

所有这些x都是长槽填充。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35605860

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档