Вопрос с собеседования · Java

Реализуй потокобезопасный счётчик Counter с методами increment() и get().

MiddleМногопоточность
Коротко

Проще всего — AtomicInteger: incrementAndGet() и get(), без блокировок. Альтернатива — synchronized на обоих методах (важно: и на чтении тоже, иначе нет видимости).

  • Ошибка — volatile int с count++: теряет обновления
  • Ошибка — synchronized только на increment: get может прочитать устаревшее значение
  • Под высокой конкуренцией — LongAdder

А ещё Расскажите про CAS, если попросят пояснить

Подробно

private final AtomicInteger c = new AtomicInteger(); increment → c.incrementAndGet(); get → c.get(). Альтернатива — synchronized на обоих методах.

Пример

class Counter {
    private final AtomicInteger value = new AtomicInteger();
    public int increment() { return value.incrementAndGet(); }
    public int get() { return value.get(); }
}

Вариант с монитором:

class Counter {
    private int value;
    public synchronized int increment() { return ++value; }
    public synchronized int get() { return value; }
}

Что хотят услышать

  • Рабочая реализация.
  • Почему volatile++ не подходит.
  • Синхронизация чтения.
  • LongAdder при высокой конкуренции.

Частые ошибки

  • volatile-счётчик с ++ (гонка).
  • synchronized только на increment, но не на get (теряется видимость).

Что спросят дальше

  • Чем LongAdder лучше AtomicLong?
  • Что гарантирует happens-before здесь?

Разбор темы

Связанные вопросы

Партнёр платформы

Разбор собеседования с sotto

После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.

Разбор собеседования