多线程Java应用程序中的性能

时间:2010-10-26 22:00:19

标签: java multithreading performance multicore

我想了解多线程环境中的性能。为此,我编写了一个小测试,我在我的机器上运行(四核英特尔,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");
    }
  }
}

我做了以下观察:

  1. java SynchronizedPerformance 1 synchronized效果非常好,每步约15 ns。
  2. java SynchronizedPerformance 2 synchronized会干扰很多,每步大约需要150 ns。
  3. 当我开始两个独立的java SynchronizedPerformance 2 synchronized进程时,每个进程大约需要100 ns。也就是说,第二次启动过程会使第一次(和第二次)更快。
  4. 我不明白第三次观察。对这种现象有什么合理的解释?

2 个答案:

答案 0 :(得分:1)

最有可能的是,无论存在多少个线程,都存在某些固定的开销 - 例如,垃圾收集或其他资源管理。

答案 1 :(得分:1)

您遇到的情况是性能完全取决于调度程序的运行方式。在#3中,当系统中的任何其他进程需要一些时间(甚至一点点)时,它将暂停您的4个线程中的一个。如果该线程在挂起时碰巧没有锁定,那么它的“对”现在可以无争议地运行,并且会有很多进展(与有争议的情况相比,以20倍的速度运行)。

当然,如果它在保持锁定时被换出,它的“对”将没有进展。因此,您有两个竞争因素,整体运行时间取决于线程持有锁的时间部分以及您获得的每种情况的惩罚/奖励。你的奖金很大,所以我希望你能看到一些整体加速。