Несколько горутин одновременно увеличивают один общий счётчик. Если делать это
без защиты, получится гонка данных и итог окажется меньше ожидаемого. Твоя
задача — защитить инкремент самодельным спинлоком на sync/atomic.
Реализуй функцию:
func SpinSum(goroutines, perGoroutine int) int
Что нужно сделать:
- запусти
goroutines горутин;
- каждая горутина
perGoroutine раз увеличивает общий счётчик на 1;
- инкремент счётчика выполняется только под спинлоком: спинлок — это
int32,
захват — успешный CompareAndSwap(0 → 1) в цикле, отпускание — Store(0);
- дождись завершения всех горутин через
sync.WaitGroup и верни значение счётчика.
Результат полностью детерминирован: ровно goroutines * perGoroutine.
SpinSum(4, 250)
// → 1000
SpinSum(50, 1000)
// → 50000
Краевые условия:
SpinSum(0, 100) → 0 (горутин нет — никто не считает);
SpinSum(1, 0) → 0 (считать нечего).
Аппаратная основа таких блокировок (атомарные инструкции, CAS) разобрана в главе
«Блокировки: железо».