我想了解多线程环境中的性能。为此,我编写了一个小测试,在我的机器(四核 Intel、Windows XP、Sun JDK 1.6.0_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 ns。
-
java SynchronizedPerformance 2 synchronized
干扰很多,每步大约需要 150 ns。
- 当我启动两个独立的进程时
java SynchronizedPerformance 2 synchronized
每个步骤每步大约需要 100 ns。也就是说,第二次启动该过程会使第一个(和第二个)过程更快。
我不明白第三个观察结果。对于这种现象有哪些合理的解释?
您遇到的情况是性能完全取决于调度程序的运行方式。在 #3 中,当系统中的任何其他进程需要一些时间(即使是一点点)时,它将挂起 4 个线程之一。如果该线程在挂起时碰巧没有持有锁,那么它的“对”现在可以无竞争地运行,并且将取得很大的进展(与有竞争的情况相比,以 20 倍的速度运行)。
当然,如果它在持有锁的情况下被换出,那么它的“对”将不会取得任何进展。因此,您有两个相互竞争的因素,并且总体运行时间取决于线程持有锁的时间比例以及每种情况下获得的惩罚/奖励。你的奖金是可观的,所以我希望像你看到的那样有一些整体加速。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)