Java多线程中的volatile和伪共享(2)

/* 缓冲行填充 */
        /* 37370571461 :不使用缓冲行执行纳秒数 */
        /* 16174480826 :使用缓冲行执行纳秒数,性能提高一半 */
        public long          p1, p2, p3, p4, p5, p6, p7;
    }

private static VolatileLong[] longs = new VolatileLong[NUM_THREADS];
    static {
        for (int i = 0; i < longs.length; i++) {
            longs[i] = new VolatileLong();
        }
    }

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

/**
    * 我们不能确定这些VolatileLong会布局在内存的什么位置。它们是独立的对象。但是经验告诉我们同一时间分配的对象趋向集中于一块。
    */
    public static void main(final String[] args) throws Exception {
        final long start = System.nanoTime();
        runTest();
        System.out.println("duration = " + (System.nanoTime() - start));
    }

private static void runTest() throws InterruptedException {
        Thread[] threads = new Thread[NUM_THREADS];

for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(new TestFlash(i));
        }

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

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

/*
    * 为了展示其性能影响,我们启动几个线程,每个都更新它自己独立的计数器。计数器是volatile long类型的,所以其它线程能看到它们的进展
    */
    @Override
    public void run() {
        long i = ITERATIONS + 1;
        while (0 != --i) {
            longs[arrayIndex].value = i;
        }
    }
}

VolatileLong通过填充一些无用的字段p1,p2,p3,p4,p5,p6,再考虑到对象头也占用8bit, 刚好把对象占用的内存扩展到刚好占64bytes(或者64bytes的整数倍)。这样就避免了一个缓存行中加载多个对象。但这个方法现在只能适应JAVA6 及以前的版本了。

  在jdk1.7环境下,由于java 7会优化掉无用的字段。因此,JAVA 7下做缓存行填充更麻烦了,需要使用继承的办法来避免填充被优化掉。把填充放在基类里面,可以避免优化(这好像没有什么道理好讲的,JAVA7的内存优化算法问题,能绕则绕)。

package basic;

public class TestFlashONJDK7 implements Runnable {

public static int            NUM_THREADS = 4;
    public final static long      ITERATIONS  = 500L * 1000L * 1000L;
    private final int            arrayIndex;
    private static VolatileLong[] longs;

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

public static void main(final String[] args) throws Exception {
        Thread.sleep(10000);
        System.out.println("starting....");
        if (args.length == 1) {
            NUM_THREADS = Integer.parseInt(args[0]);
        }

longs = new VolatileLong[NUM_THREADS];
        for (int i = 0; i < longs.length; i++) {
            longs[i] = new VolatileLong();
        }
        final long start = System.nanoTime();
        runTest();
        System.out.println("duration = " + (System.nanoTime() - start));
    }

private static void runTest() throws InterruptedException {
        Thread[] threads = new Thread[NUM_THREADS];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(new TestFlashONJDK7(i));
        }
        for (Thread t : threads) {
            t.start();
        }
        for (Thread t : threads) {
            t.join();
        }
    }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/9020863d289a098b2e34d0a03afea2fd.html