原文:False Shareing && Java 7 (依然是马丁的博客) 译者:杨帆 校对:方腾飞
在我前一篇有关伪共享的博文中,我提到了可以加入闲置的long字段来填充缓存行来避免伪共享。但是看起来Java 7变得更加智慧了,它淘汰或者是重新排列了无用的字段,这样我们之前的办法在Java 7下就不奏效了,但是伪共享依然会发生。我在不同的平台上实验了一些列不同的方案,并且最终发现下面的代码是最可靠的。(译者注:下面的是最终版本,马丁在大家的帮助下修改了几次代码)
01 |
import java.util.concurrent.atomic.AtomicLong;
|
02 |
03 |
public final class FalseSharing
|
04 |
implements Runnable
|
05 |
{ |
06 |
public final static int NUM_THREADS = 4 ; // change
|
07 |
public final static long ITERATIONS = 500L * 1000L * 1000L;
|
08 |
private final int arrayIndex;
|
09 |
10 |
private static PaddedAtomicLong[] longs = new PaddedAtomicLong[NUM_THREADS];
|
11 |
static
|
12 |
{
|
13 |
for ( int i = 0 ; i < longs.length; i++)
|
14 |
{
|
15 |
longs[i] = new PaddedAtomicLong();
|
16 |
}
|
17 |
}
|
18 |
19 |
public FalseSharing( final int arrayIndex)
|
20 |
{
|
21 |
this .arrayIndex = arrayIndex;
|
22 |
}
|
23 |
24 |
public static void main( final String[] args) throws Exception
|
25 |
{
|
26 |
final long start = System.nanoTime();
|
27 |
runTest();
|
28 |
System.out.println( "duration = " + (System.nanoTime() - start));
|
29 |
}
|
30 |
31 |
private static void runTest() throws InterruptedException
|
32 |
{
|
33 |
Thread[] threads = new Thread[NUM_THREADS];
|
34 |
35 |
for ( int i = 0 ; i < threads.length; i++)
|
36 |
{
|
37 |
threads[i] = new Thread( new FalseSharing(i));
|
38 |
}
|
39 |
40 |
for (Thread t : threads)
|
41 |
{
|
42 |
t.start();
|
43 |
}
|
44 |
45 |
for (Thread t : threads)
|
46 |
{
|
47 |
t.join();
|
48 |
}
|
49 |
}
|
50 |
51 |
public void run()
|
52 |
{
|
53 |
long i = ITERATIONS + 1 ;
|
54 |
while ( 0 != --i)
|
55 |
{
|
56 |
longs[arrayIndex].set(i);
|
57 |
}
|
58 |
}
|
59 |
60 |
// 这段代码的来历可以看4楼的回复
|
61 |
public static long sumPaddingToPreventOptimisation( final int index)
|
62 |
{
|
63 |
PaddedAtomicLong v = longs[index];
|
64 |
return v.p1 + v.p2 + v.p3 + v.p4 + v.p5 + v.p6;
|
65 |
}
|
66 |
67 |
public static class PaddedAtomicLong extends AtomicLong
|
68 |
{
|
69 |
public volatile long p1, p2, p3, p4, p5, p6 = 7L;
|
70 |
}
|
71 |
} |
用以上这种办法我获得了和上一篇博客里提到的相近的性能,读者可以把PaddedAtomicLong里面那行填充物注释掉再跑测试看看效果。
我想我们大家都有权去跟Oracle投诉,让他们在JDK里默认加入缓存行对齐的函数或者是被填充好的原子类型,这和其他一些底层改变会让Java成为一门真真正正的并发编程语言。我们一直以来不断的在听到他们讲多核时代正在到来,但是我要说的是在这方面Java需要快点赶上来。
时间: 2024-09-20 14:30:31