CPU缓存中的cache line缓存行是缓存的最小单位,同一个时刻内只允许一个cpu内核进行操作。一般,缓存行的大小为64字节,这样的大小可以存放多个java对象的对象头。因此,当两个不同的线程同时访问位于同一个缓存行内的对象或变量的时候,需要以同步的方式进行访问,这种现象称为伪共享(false sharing)。
Martin Thompson 用于演示false sharing的示例程序:
public final class FalseSharing implements Runnable{ public final static int NUM_THREADS = 6; // change public final static long ITERATIONS = 500L * 1000L * 1000L; private final int arrayIndex; private static VolatileLong[] longs = new VolatileLong[NUM_THREADS]; static { for (int i = 0; i < longs.length; i++) { longs[i] = new VolatileLong(); } } public FalseSharing(final int arrayIndex) { this.arrayIndex = arrayIndex; } /** * 启动NUM_THREADS个线程 * */ 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 FalseSharing(i)); } //依次启动t0 t1 t2 t3 for (Thread t : threads) { t.start(); } //主线程等待t0 t1 t2 t3都执行完run方法 for (Thread t : threads) { t.join(); } } @Override public void run() { long i = ITERATIONS + 1; while (0 != --i) { longs[arrayIndex].value = i; } } public final static class VolatileLong { public volatile long value = 0L; public long p1, p2, p3, p4, p5, p6; //对缓存行的填充,java对象从缓存行的第8个字节开始对齐,故7个long型即可填充满一个缓存行 } public static void main(String[] args) throws InterruptedException{ final long start = System.nanoTime(); runTest(); System.out.println("duration = " + (System.nanoTime()-start)); } }
以下是我自家用笔记本电脑cpu配置: