Производительность в многопоточном приложении Java - PullRequest
2 голосов
/ 27 октября 2010

Я хочу понять производительность в многопоточных средах.Для этого я написал небольшой тест, который я выполнил на своем компьютере (четырехъядерный процессор 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");
    }
  }
}

Я сделал следующие наблюдения:

  1. java SynchronizedPerformance 1 synchronized работает довольно хорошо и занимает около 15 нс за шаг.
  2. java SynchronizedPerformance 2 synchronized много мешает и занимает около 150 нс за шаг.
  3. Когда я запускаю два независимых процесса с java SynchronizedPerformance 2 synchronized, каждый из них занимает около 100 нс за шаг.То есть, запуск процесса во второй раз делает первый (и второй) быстрее.

Я не понимаю третьего наблюдения.Какие правдоподобные объяснения существуют для этого явления?

Ответы [ 2 ]

1 голос
/ 27 октября 2010

Вы столкнулись с ситуацией, когда производительность полностью зависит от того, как работает планировщик.В # 3, когда любому другому процессу в системе требуется некоторое время (даже немного), он приостанавливает один из ваших 4 потоков.Если этот поток не удерживает блокировку, когда он приостановлен, его «пара» теперь может работать без всяких сомнений и будет добиваться большого прогресса (работает с 20-кратной скоростью по сравнению с оспариваемой ситуацией).

Конечно, если он заменяется, когда удерживает блокировку, его «пара» не будет прогрессировать.Таким образом, у вас есть два конкурирующих фактора, и общее время выполнения зависит от доли времени, в течение которого блокировка удерживается потоком, и пенальти / бонуса, которые вы получаете за каждую ситуацию.Ваш бонус значительный, поэтому я ожидаю некоторого общего ускорения, как вы видели.

1 голос
/ 27 октября 2010

Наиболее вероятно, что существуют определенные фиксированные накладные расходы, которые существуют независимо от того, сколько потоков существует, например, сборщик мусора или управление другими ресурсами.

...