Между кем и за что возникает конкуренция в Go-программах?

Ответ

В 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) для простых операций, таких как инкремент.