2

目标:在java中测试虚假共享

问题:我在字段上添加了@Contended 注释,但类布局没有显示填充字节。虚假分享仍然发生。
我有 3 个测试:

  1. 没有填充
  2. 添加长变量作为填充字节
  3. 使用@Contended 注解添加填充字节

环境

  • macos Monterey 12.1 MacBookPro m1 max
  • OpenJDK 运行时环境 (Zulu 8.52.0.23-CA-macos-aarch64) (build 1.8.0_282-b08)

ps:我已经尝试添加-XX:-RestrictContended选项,但仍然无法正常工作。

这是我的测试代码:

public class FalseSharing {
    public final static int NUM_THREADS = 4; // change

    public static class FalseSharingTestBase {
        public final static long ITERATIONS = 500*1000*1000L;

        protected final int arrayIndex;


        public FalseSharingTestBase(final int arrayIndex) {
            this.arrayIndex = arrayIndex;
        }


    }

    static class TestCase1 extends FalseSharingTestBase implements Runnable {

        protected static VolatileLong1[] longs1 = new VolatileLong1[NUM_THREADS];

        static {
            for (int i = 0; i < longs1.length; i++) {
                longs1[i] = new VolatileLong1();
            }
        }

        public TestCase1(int arrayIndex) {
            super(arrayIndex);
        }

        @Override
        public void run() {
            long i = ITERATIONS + 1;
            while (0 != --i) {
                longs1[arrayIndex].value = i;
            }
        }
    }

    static class TestCase2 extends FalseSharingTestBase implements Runnable {

        protected static VolatileLong2[] longs2 = new VolatileLong2[NUM_THREADS];
        static {
            for (int i = 0; i < longs2.length; i++) {
                longs2[i] = new VolatileLong2();
            }
        }
        public TestCase2(int arrayIndex) {
            super(arrayIndex);
        }

        @Override
        public void run() {
            long i = ITERATIONS + 1;
            while (0 != --i) {
                longs2[arrayIndex].value = i;
            }
        }
    }

    static class TestCase3 extends FalseSharingTestBase implements Runnable {

        protected static VolatileLong3[] longs3 = new VolatileLong3[NUM_THREADS];
        static {
            for (int i = 0; i < longs3.length; i++) {
                longs3[i] = new VolatileLong3();
            }

        }
        public TestCase3(int arrayIndex) {
            super(arrayIndex);
        }

        @Override
        public void run() {
            long i = ITERATIONS + 1;
            while (0 <= --i) {
                longs3[arrayIndex].value = i;
            }
        }
    }

    public final static class VolatileLong1 {
        public volatile long value = 0L;
    }

    // long padding避免false sharing
    public final static class VolatileLong2 {
        volatile long p0, p1, p2, p3, p4, p5, p6, p7;
        volatile long p10, p11, p12, p13, p14, p15, p16, p17;
        public volatile long value = 0L;
        volatile long q0, q1, q2, q3, q4, q5, q6, q7;
        volatile long q10, q11, q12, q13, q14, q15, q16, q17;
    }

    public final static class VolatileLong3 {
        @sun.misc.Contended
        public volatile long value = 0L;
    }

    public static void main(final String[] args) throws Exception {
        System.out.println("volatile1 layout: ");
        ObjectUtil.printCls(VolatileLong1.class);

        System.out.println("volatile2 layout: ");
        ObjectUtil.printCls(VolatileLong2.class);

        System.out.println("volatile3 layout: ");
        ObjectUtil.printCls(VolatileLong3.class);

        long start = System.nanoTime();

        Thread[] threads = new Thread[NUM_THREADS];

        for (int i = 0; i < threads.length; i++) {
//            threads[i] = new Thread(new TestCase1(i));
//            threads[i] = new Thread(new TestCase2(i));
            threads[i] = new Thread(new TestCase3(i));
        }

        for (Thread t : threads) {
            t.start();
        }

        for (Thread t : threads) {
            t.join();
        }

        System.out.println("duration = " + (System.nanoTime() - start));
    }

}

输出:

volatile1 layout: 
# WARNING: Unable to attach Serviceability Agent. Unable to attach even with module exceptions: [org.openjdk.jol.vm.sa.SASupportException: Sense failed., org.openjdk.jol.vm.sa.SASupportException: Sense failed., org.openjdk.jol.vm.sa.SASupportException: Sense failed.]
cn.windery.learning.jvm.cache.FalseSharing$VolatileLong1 object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     N/A
  8   4        (object header: class)    N/A
 12   4        (alignment/padding gap)   
 16   8   long VolatileLong1.value       N/A
Instance size: 24 bytes
Space losses: 4 bytes internal + 0 bytes external = 4 bytes total

volatile2 layout: 
cn.windery.learning.jvm.cache.FalseSharing$VolatileLong2 object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     N/A
  8   4        (object header: class)    N/A
 12   4        (alignment/padding gap)   
 16   8   long VolatileLong2.p0          N/A
 24   8   long VolatileLong2.p1          N/A
 32   8   long VolatileLong2.p2          N/A
 40   8   long VolatileLong2.p3          N/A
 48   8   long VolatileLong2.p4          N/A
 56   8   long VolatileLong2.p5          N/A
 64   8   long VolatileLong2.p6          N/A
 72   8   long VolatileLong2.p7          N/A
 80   8   long VolatileLong2.p10         N/A
 88   8   long VolatileLong2.p11         N/A
 96   8   long VolatileLong2.p12         N/A
104   8   long VolatileLong2.p13         N/A
112   8   long VolatileLong2.p14         N/A
120   8   long VolatileLong2.p15         N/A
128   8   long VolatileLong2.p16         N/A
136   8   long VolatileLong2.p17         N/A
144   8   long VolatileLong2.value       N/A
152   8   long VolatileLong2.q0          N/A
160   8   long VolatileLong2.q1          N/A
168   8   long VolatileLong2.q2          N/A
176   8   long VolatileLong2.q3          N/A
184   8   long VolatileLong2.q4          N/A
192   8   long VolatileLong2.q5          N/A
200   8   long VolatileLong2.q6          N/A
208   8   long VolatileLong2.q7          N/A
216   8   long VolatileLong2.q10         N/A
224   8   long VolatileLong2.q11         N/A
232   8   long VolatileLong2.q12         N/A
240   8   long VolatileLong2.q13         N/A
248   8   long VolatileLong2.q14         N/A
256   8   long VolatileLong2.q15         N/A
264   8   long VolatileLong2.q16         N/A
272   8   long VolatileLong2.q17         N/A
Instance size: 280 bytes
Space losses: 4 bytes internal + 0 bytes external = 4 bytes total

volatile3 layout: 
cn.windery.learning.jvm.cache.FalseSharing$VolatileLong3 object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     N/A
  8   4        (object header: class)    N/A
 12   4        (alignment/padding gap)   
 16   8   long VolatileLong3.value       N/A
Instance size: 24 bytes
Space losses: 4 bytes internal + 0 bytes external = 4 bytes total

duration = 1468214167
4

1 回答 1

0

那是我的愚蠢错误。
我使用 Intellij IDEA 程序参数来添加-XX:-RestrictContended运行配置。但它应该是VM选项。
默认情况下,它不显示。我在那里添加了选项,它现在可以工作了。

这是最终输出:

volatile1 layout: 
# WARNING: Unable to attach Serviceability Agent. Unable to attach even with module exceptions: [org.openjdk.jol.vm.sa.SASupportException: Sense failed., org.openjdk.jol.vm.sa.SASupportException: Sense failed., org.openjdk.jol.vm.sa.SASupportException: Sense failed.]
cn.windery.learning.jvm.cache.FalseSharing$VolatileLong1 object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     N/A
  8   4        (object header: class)    N/A
 12   4        (alignment/padding gap)   
 16   8   long VolatileLong1.value       N/A
Instance size: 24 bytes
Space losses: 4 bytes internal + 0 bytes external = 4 bytes total

volatile2 layout: 
cn.windery.learning.jvm.cache.FalseSharing$VolatileLong2 object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     N/A
  8   4        (object header: class)    N/A
 12   4        (alignment/padding gap)   
 16   8   long VolatileLong2.p0          N/A
 24   8   long VolatileLong2.p1          N/A
 32   8   long VolatileLong2.p2          N/A
 40   8   long VolatileLong2.p3          N/A
 48   8   long VolatileLong2.p4          N/A
 56   8   long VolatileLong2.p5          N/A
 64   8   long VolatileLong2.p6          N/A
 72   8   long VolatileLong2.p7          N/A
 80   8   long VolatileLong2.p10         N/A
 88   8   long VolatileLong2.p11         N/A
 96   8   long VolatileLong2.p12         N/A
104   8   long VolatileLong2.p13         N/A
112   8   long VolatileLong2.p14         N/A
120   8   long VolatileLong2.p15         N/A
128   8   long VolatileLong2.p16         N/A
136   8   long VolatileLong2.p17         N/A
144   8   long VolatileLong2.value       N/A
152   8   long VolatileLong2.q0          N/A
160   8   long VolatileLong2.q1          N/A
168   8   long VolatileLong2.q2          N/A
176   8   long VolatileLong2.q3          N/A
184   8   long VolatileLong2.q4          N/A
192   8   long VolatileLong2.q5          N/A
200   8   long VolatileLong2.q6          N/A
208   8   long VolatileLong2.q7          N/A
216   8   long VolatileLong2.q10         N/A
224   8   long VolatileLong2.q11         N/A
232   8   long VolatileLong2.q12         N/A
240   8   long VolatileLong2.q13         N/A
248   8   long VolatileLong2.q14         N/A
256   8   long VolatileLong2.q15         N/A
264   8   long VolatileLong2.q16         N/A
272   8   long VolatileLong2.q17         N/A
Instance size: 280 bytes
Space losses: 4 bytes internal + 0 bytes external = 4 bytes total

volatile3 layout: 
cn.windery.learning.jvm.cache.FalseSharing$VolatileLong3 object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     N/A
  8   4        (object header: class)    N/A
 12 132        (alignment/padding gap)   
144   8   long VolatileLong3.value       N/A
Instance size: 152 bytes
Space losses: 132 bytes internal + 0 bytes external = 132 bytes total

duration = 319432958
于 2022-01-25T02:46:05.130 回答