我想了解多线程环境中的性能。为此,我编写了一个在我的计算机上运行的小测试(四核Intel、Windows XP、Sun JDK 1.6.0 U 20),结果令人惊讶。
测试基本上是一个线程安全计数器,使用
synchronized
关键字或显式锁。代码如下:
import java.util.concurrent.locks.ReentrantLock;
public class SynchronizedPerformance {
static class Counter {
private static final int MAX = 1 << 24;
int count;
long lastLog = 0;
private final ReentrantLock lock = new ReentrantLock();
private int incrementAndGet() {
count++;
if (count == MAX) {
long now = System.nanoTime();
if (lastLog != 0) {
long elapsedTime = now - lastLog;
System.out.printf("counting took %.2f ns\n", Double.valueOf((double)elapsedTime / MAX));
}
lastLog = now;
count = 0;
}
return count;
}
synchronized int synchronizedIncrementAndGet() {
return incrementAndGet();
}
int lockedIncrementAndGet() {
lock.lock();
try {
return incrementAndGet();
} finally {
lock.unlock();
}
}
}
static class SynchronizedCounterAccessor implements Runnable {
private final Counter counter;
public SynchronizedCounterAccessor(Counter counter) {
this.counter = counter;
}
@Override
public void run() {
while (true)
counter.synchronizedIncrementAndGet();
}
}
static class LockedCounterAccessor implements Runnable {
private final Counter counter;
public LockedCounterAccessor(Counter counter) {
this.counter = counter;
}
@Override
public void run() {
while (true)
counter.lockedIncrementAndGet();
}
}
public static void main(String[] args) {
Counter counter = new Counter();
final int n = Integer.parseInt(args[0]);
final String mode = args[1];
if (mode.equals("locked")) {
for (int i = 0; i < n; i++)
new Thread(new LockedCounterAccessor(counter), "ca" + i).start();
} else if (mode.equals("synchronized")) {
for (int i = 0; i < n; i++)
new Thread(new SynchronizedCounterAccessor(counter), "ca" + i).start();
} else {
throw new IllegalArgumentException("locked|synchronized");
}
}
}
我做了以下观察:
java SynchronizedPerformance 1 synchronized
工作得很好,每一步大约需要15纳秒。
java SynchronizedPerformance 2 synchronized
干扰很大,每步大约需要150纳秒。
当我开始两个独立的过程
Java同步性能2同步
每一步大约需要100纳秒。也就是说,第二次启动流程会使第一次(和第二次)更快。
我不明白第三个观察结果。对于这种现象,有什么合理的解释?