我读过一篇有关缓存行填充的文章,网址是:
https://mechanical-sympathy.blogspot.com/2011/07/false-sharing.html
它有一个像这样的例子:
public final class FalseSharing implements Runnable {
public final static int NUM_THREADS = 4; // 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;
}
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 FalseSharing(i));
}
for (Thread t : threads) {
t.start();
}
for (Thread t : threads) {
t.join();
}
}
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; // comment out
}
}
问题1:
如果要避免错误共享,则应确保VolatileLong对象为64个字节,长值0L为8个字节,p1,p2,p3,p4,p5,p6为48个字节,那么其余8个字节到底是什么? ?
问题2:
我已经执行了这个程序,结果是:22951146607
如果我在VolatileLong中删除变量p6,则结果为:19457942328,它小于使用p6的值,而如果不使用p6,则它可能会遭受错误共享。当然,每次的结果都是不同的,但是通常使用p6的时间比不使用p6的时间更多,这并没有显示出缓存行填充的优势。
最佳答案
VolatileLong
缺少的另外8个字节由object header占用。因此,即使在源代码中仅可见56个字节,VolatileLong
的总大小为64个字节。
最后,以适当的micro benchmark harness进行测试以获得可靠的结果会更加有效。