Выбор ответа Middle sync и атомики спрашивают часто обновлено
Копирование структуры с мьютексом
Вопрос
В чём ошибка кода?
type SafeCounter struct {
mu sync.Mutex
m map[string]int
}
func (c SafeCounter) Inc(k string) {
c.mu.Lock()
defer c.mu.Unlock()
c.m[k]++
}
Попробуйте сами
Выберите вариант, и откроется разбор.
Показать ответ и разбор
Коротко
Правильный ответ: Ресивер по значению копирует мьютекс, защиты нет. У Inc ресивер SafeCounter по значению, поэтому c.mu и c.m здесь копия структуры.
Варианты ответа
- Для мапы нужен RWMutex, обычный Mutex её не защитит
- Ресивер по значению копирует мьютекс, защиты нетправильный ответ
- defer нельзя использовать с Unlock, нужен явный вызов
- Мьютекс нужно инициализировать через sync.NewMutex()
Разбор
У Inc ресивер SafeCounter по значению, поэтому c.mu и c.m здесь копия структуры. Мапа внутри общая (мапа это указатель), а мьютекс у каждого вызова свой, поэтому параллельные вызовы пишут в мапу без защиты. go vet (copylocks) сообщает об этом. Исправление: func (c *SafeCounter) Inc. RWMutex тут не поможет, defer с Unlock обычная практика, конструктора у Mutex нет, нулевое значение готово.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.
Ещё по теме «sync и атомики»
- Глобальный максимум через CompareAndSwap
- Конкурентные переводы между счетами без дедлока
- Шардированная мапа с мьютексом на шард
- Что выведет Go: atomic.Int64 из 100 горутин
- Что выведет Go: sync.Once и OnceValue
- Код-ревью Go: кеш на RWMutex
- Код-ревью Go: ленивый синглтон и горячая перезагрузка конфига
- Типизированные атомики