Проверяет понимание роли mutex в буферизированном канале и того, какие данные он защищает.
Mutex (mutual exclusion) — это примитив синхронизации, который гарантирует, что только одна горутина может выполнять определённый участок кода в данный момент времени. В контексте буферизированного канала mutex защищает не сам канал, а общие данные, которые горутины используют при отправке или получении сообщений.
Буферизированный канал сам по себе потокобезопасен: операции отправки и получения атомарны. Однако если горутины модифицируют общие переменные (например, счётчики, структуры) до или после работы с каналом, возникает риск гонки данных. Mutex решает эту проблему, ограничивая доступ к критической секции.
type Counter struct {
mu sync.Mutex
value int
}
func (c *Counter) Increment() {
c.mu.Lock()
defer c.mu.Unlock()
c.value++
}
func worker(ch chan int, c *Counter) {
for v := range ch {
c.Increment()
fmt.Println(v)
}
}
func main() {
ch := make(chan int, 10)
c := &Counter{}
for i := 0; i < 5; i++ {
go worker(ch, c)
}
for i := 0; i < 100; i++ {
ch <- i
}
close(ch)
}Здесь mutex защищает поле value от одновременного изменения. Канал используется для передачи чисел, но счётчик — общий ресурс, требующий блокировки.
Mutex в сочетании с буферизированным каналом полезен, когда нужно ограничить количество одновременных операций или защитить общее состояние. Например, в пуле воркеров, где несколько горутин обрабатывают задачи и обновляют общую статистику. Без mutex данные могут быть повреждены из-за гонок.
Вывод: mutex защищает общие данные, а не сам канал. Используйте его, когда горутины работают с разделяемыми переменными вне канала, чтобы избежать гонок данных и обеспечить корректность программы.