Ответ
В Go конкуренция (в контексте проблем) возникает в первую очередь между горутинами (goroutines).
Они конкурируют за доступ к общим изменяемым ресурсам (shared mutable state). Чаще всего это:
- Переменные
- Срезы (slices)
- Карты (maps)
- Поля структур
Когда две или более горутины одновременно пытаются читать и изменять одни и те же данные без надлежащей синхронизации, возникает состояние гонки (race condition). Это приводит к непредсказуемому поведению программы и трудноуловимым ошибкам.
Пример состояния гонки:
func main() {
var counter int // Общий ресурс
// Запускаем 1000 горутин, которые конкурируют за доступ к counter
for i := 0; i < 1000; i++ {
go func() {
counter++ // Неатомарная операция: чтение, инкремент, запись
}()
}
time.Sleep(time.Second)
// Результат будет непредсказуем и почти никогда не равен 1000
fmt.Println("Final counter:", counter)
}
Для безопасной работы с общими ресурсами в Go используются примитивы синхронизации:
- Мьютексы (
sync.Mutex
) для эксклюзивного доступа. - Каналы (channels) для безопасной передачи данных между горутинами.
- Атомарные операции (
sync/atomic
) для простых операций, таких как инкремент.