MXStat
MXStat
Введите текст для поиска
Расширенный поиск каналов
  • Вход на сайт
  • Каталог
    Каталог каналов Региональные подборки Поиск каналов
    Добавить канал
  • Рейтинги
    Рейтинг каналов Рейтинг публикаций
    Рейтинги брендов и персон
  • Аналитика
  • Поиск по публикациям
  • Мониторинг Max
Библиотека Go (Golang) разработчика

28 Sep, 11:46

Открыть в Max Поделиться

🧠 Go Memory Model: Почему ваша горутина слепая (и что такое Happens-Before)

Напишем простейший код. Одна горутина меняет флаг, другая ждет этого изменения:

var done bool
var msg string

func setup() {
msg = "hello, world"
done = true
}

func main() {
go setup()

// Ждем, пока setup() закончит работу
for !done {
}

fmt.Println(msg)
}

Джун посмотрит на этот код и скажет: "Ну, он выведет `hello, world`".
Сеньор посмотрит на этот код и скажет: "Этот код может уйти в бесконечный цикл, может вывести пустую строку, а может работать нормально. Это лотерея".

Добро пожаловать в жестокий мир Go Memory Model.

Иллюзия мгновенной памяти

Мы привыкли думать, что память - это единый монолит. Записал переменную — она тут же стала доступна всем. Но в реальности код выполняется на современных многоядерных процессорах. У каждого ядра есть свой сверхбыстрый локальный кэш (L1/L2).

Когда горутина setup пишет done = true, процессор может положить это значение в свой локальный кэш и не сбрасывать его в общую оперативную память (RAM) еще миллисекунды. А горутина main, работающая на другом ядре, будет бесконечно читать старое значение done == false из своего собственного кэша.

Но и это не всё! Компилятор Go невероятно умен. Он смотрит на цикл for !done {} и думает: "Внутри этого цикла переменная done не меняется. Зачем мне читать её из памяти на каждой итерации? Прочитаю один раз, сохраню в регистр процессора и буду проверять его". Итог - вечный цикл (Infinite Loop).

Святой Грааль: Happens-Before (Происходит-До)

Чтобы навести порядок в этом хаосе, создатели Go написали формальный документ - Модель Памяти (Memory Model). В её основе лежит концепция Happens-Before.

> Если событие A происходит до события B, то Модель Памяти гарантирует, что горутина, выполняющая B, абсолютно точно увидит изменения, сделанные в A.

Если между действиями нет связи Happens-Before, компилятор и процессор имеют право переупорядочивать инструкции как им вздумается, а кэши могут не синхронизироваться.

Как создать связь Happens-Before?

Вам нужны примитивы синхронизации. Они работают как жесткие барьеры памяти (Memory Barriers), заставляя процессоры сбросить кэши, а компилятор - прекратить умничать с перестановкой строк кода.

✅ 1. Каналы (Channels)
Отправка данных в канал происходит до завершения чтения из этого канала в другой горутине.

c := make(chan struct{})
go func() {
msg = "hello"
c <- struct{}{} // Happens-Before
}()
<-c // Ждем
fmt.Println(msg) // 100% увидит "hello"

✅ 2. Мьютексы (Mutexes)
Снятие блокировки mu.Unlock() происходит до успешного захвата mu.Lock() другой горутиной.

✅ 3. Атомики (sync/atomic)
Начиная с Go 1.19, в Модель Памяти официально добавили пакет atomic. Атомарные операции теперь гарантированно создают связь Happens-Before.

✅ 4. Жизненный цикл горутины
Создание горутины (go func()) происходит до начала выполнения её кода. А вот завершение горутины не имеет гарантий! (Именно поэтому нам нужен sync.WaitGroup, чтобы дождаться её финала).

🔥 Senior Tip: Не пытайтесь обмануть систему

Существует соблазн написать код, который работает "без блокировок", опираясь на задержки: time.Sleep(time.Millisecond). Это называется data race (состояние гонки). Даже если на вашей машине с процессором Intel код работает идеально, завтра его скомпилируют под ARM-архитектуру (Apple Silicon или AWS Graviton), у которой гораздо более слабая модель памяти процессора, и ваш код рассыплется в пыль.

Всегда используйте флаг -race во время локальной разработки и CI: go test -race ./.... Он ловит отсутствие связей Happens-Before с хирургической точностью.

#golang #underhood #architecture #performance #memorymodel

👉 @golang_lib

363 6
Каталог
Каталог каналов Подборки каналов Поиск каналов Добавить канал
Рейтинги
Рейтинг каналов Max
Контакты
Написать в Max Написать в Telegram Написать на почту
Всякая всячина
Пользовательское соглашение Политика конфиденциальности
Наши каналы
MXStat в Telegram MXStat в Max
Наши боты
MXAuthBot MXAnalyticsBot
Made by TGStat