Вопрос

Мне нужно привлекать счет long со следующими требованиями/фактами:

  • Увеличение счетчика должно занять как можно меньше времени.
  • Счетчик будет записан только одним потоком.
  • Чтение из стойки будет сделано в другой ветке.
  • Счетчик будет регулярно увеличиваться (до нескольких тысяч раз в секунду), но будет читать только один раз каждые пять секунд.
  • Точная точность не является обязательной, только приблизительное представление о размере счетчика достаточно хорошо.
  • Счетчик никогда не очищается, уменьшается.

Основываясь на этих требованиях, как бы вы решили реализовать свой счетчик? Как простой long, как volatile long или используя AtomicLong? Почему?

На данный момент у меня есть volatile long Но было интересно, будет ли другой подход лучше. Я также увеличиваю свое долгое время, делая ++counter в отличие от counter++. Анкет Это действительно более эффективно (как я верил в другое место), потому что не выполняется задания?

Это было полезно?

Решение

Учитывая эти наборы требований, я считать что volatile Долго должно быть достаточно. Счетчик не будет неверным с неvolatile Долго, но читатель может читать устаревшую информацию в этом случае.

Одна проблема в том, что читает и пишет long находятся нет требуется быть атомным, посредством Спецификация JVM Если это не объявлено volatile. Анкет Это означало бы, что поток для чтения может получить в значительной степени фиктивное значение, если он считывает значение, в то время как письменный поток обновил одну часть значения, но не другую.

Разница между ++counter а также counter++ является вероятно Неактуально, поскольку JVM поймет, что значение выражения больше не используется, и эти два в этом случае эквивалентны.

Другие советы

В Java 8 используйте Longadder, который даже лучше, чем Atomiclong, где содействие нити высока.

Longadder Javadoc:

Этот класс обычно предпочтительнее Atomiclong, когда несколько потоков обновляют общую сумму, которая используется для таких целей, как сбор статистики, а не для мелкозернистого управления синхронизацией. При низком конфере обновления эти два класса имеют сходные характеристики. Но при высоком соревнованиях ожидаемая пропускная способность этого класса значительно выше, за счет более высокого потребления пространства.

Каковы требования времени для вашей программы? Не могли бы вы обойтись с необразованным Int и Racy-Reads?

10^4 приращения / секунда - 1 каждые 100 usec. Эффективность не проблема, но атомность может быть. У вас может быть 2 копии этого, и когда он читается, если они не равны, читайте еще раз.

Этот статья рассказывает о возможных способах реализации счетчика, я думаю, что эта реализация должна работать для вас

class LessNaiveVolatieIdGenerator {
private static volatile long id = 0;
public static long nextId() {
    long nextId = (id = id + 1); // or nextId = id++;
    return nextId;
}

}

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top