Gymterview
senior

Напишите потокобезопасную реализацию класса с неблокирующим методом BigInteger next(), который возвращает элементы последовательности: [1, 2, 4, 8, 16, ...]

Задача: каждый вызов next() должен возвращать следующую степень двойки. Реализация через CAS-цикл с AtomicReference<BigInteger>.

Код: потокобезопасный генератор степеней двойки
class PowerOfTwo {
    private AtomicReference<BigInteger> current = new AtomicReference<>(null);

    BigInteger next() {
        BigInteger recent, next;
        do {
            recent = current.get();
            next = (recent == null)
                ? BigInteger.valueOf(1)         // Первый вызов → 1 (2^0)
                : recent.shiftLeft(1);          // Сдвиг влево = умножение на 2
        } while (!current.compareAndSet(recent, next));
        return next;
    }
}

Как это работает:

  1. Поток читает текущее значение.
  2. Вычисляет следующее (сдвиг влево на 1 бит = умножение на 2).
  3. Атомарно пытается обновить значение через CAS.
  4. Если другой поток успел обновить — CAS вернёт false, цикл повторится с новым значением.

Гарантии: каждое значение последовательности будет возвращено ровно одному потоку, без пропусков и дублирований. BigInteger — неизменяемый, поэтому shiftLeft создаёт новый объект, не модифицируя старый.

На собеседовании это задание проверяет умение применять CAS-цикл для реальной задачи. Обратите внимание на использование BigInteger вместо long — последовательность быстро превысит Long.MAX_VALUE.