Что такое атомики и почему они быстрее мьютексов в Go
Что проверяют
Понимаете ли вы, что скрыто под словом «быстрее», и знаете ли границы применимости. Вопрос отсеивает тех, кто меняет мьютекс на атомик везде подряд и получает либо гонку по смыслу, либо просадку под конкуренцией.
Как отвечать
Атомарная операция выполняется процессором как неделимая над одним машинным словом: чтение, запись, сложение, обмен, сравнение с обменом. В стандартной библиотеке это пакет sync/atomic и типы вроде atomic.Int64, atomic.Bool, atomic.Pointer с методами Load, Store, Add, Swap, CompareAndSwap.
var hits atomic.Int64
func handle() {
hits.Add(1)
}Почему быстрее: это одна процессорная инструкция над строкой кэша, без участия планировщика. Мьютекс в свободном состоянии тоже начинается с атомарного сравнения с обменом, но при занятой блокировке горутина паркуется, и к стоимости добавляются уход в рантайм и последующее пробуждение.
Отсюда честная формулировка: атомик выигрывает не у мьютекса вообще, а у мьютекса под конкуренцией, и только там, где защищаемое состояние помещается в одно слово. Счётчик, флаг, указатель на неизменяемый снимок конфигурации: да. Инвариант из нескольких полей: нет, тут нужен мьютекс.
Полезно добавить, что модель памяти языка описывает операции этого пакета как последовательно согласованные, то есть на них допустимо строить отношение happens-before.
Где спотыкаются
Считают атомики бесплатными. Под высокой конкуренцией цикл повторных попыток крутится вхолостую, а строка кэша со счётчиком гоняется между ядрами. Шардирование счётчика или обычный мьютекс нередко оказываются быстрее, и решает это только замер.
Защищают атомиками несколько переменных сразу. Каждая операция атомарна по отдельности, но пара операций уже нет: Load, вычисление и Store это готовая гонка, вместо неё нужен Add или цикл вокруг CompareAndSwap.
Смешивают атомарный и обычный доступ к одной переменной или копируют структуру, внутри которой лежит атомик. Первое остаётся гонкой, второе даёт вторую независимую копию состояния, поэтому такие значения передают по указателю, а go vet ругается на явное копирование.