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).
- Атомарно пытается обновить значение через CAS.
- Если другой поток успел обновить — CAS вернёт
false, цикл повторится с новым значением.
Гарантии: каждое значение последовательности будет возвращено ровно одному потоку, без пропусков и дублирований. BigInteger — неизменяемый, поэтому shiftLeft создаёт новый объект, не модифицируя старый.
На собеседовании это задание проверяет умение применять CAS-цикл для реальной задачи. Обратите внимание на использование
BigIntegerвместоlong— последовательность быстро превыситLong.MAX_VALUE.