// Что будет выведено?

В этом коде возможна ситуация бесконечного цикла. Переменная done изменяется в горутине, но в главной горутине нет механизма синхронизации или использования атомарных операций, чтобы гарантировать видимость изменений.

Короткий ответ

Что ответить на собеседовании

В этом коде возможна ситуация бесконечного цикла. Переменная done изменяется в горутине, но в главной горутине нет механизма синхронизации или использования атомарных операций, чтобы гарантировать видимость изменений.

Подробный разбор

Ответ с пояснениями

Условие

// Что будет выведено?

package main

import (
    "fmt"
    "runtime"
)

func main() {
    runtime.GOMAXPROCS(1)
    done := false
    go func() {
        done = true
    }()
    for !done {
    }
    fmt.Println("finished")
}

Ответ

В этом коде возможна ситуация бесконечного цикла. Переменная done изменяется в горутине, но в главной горутине нет механизма синхронизации или использования атомарных операций, чтобы гарантировать видимость изменений.

Из-за оптимизаций компилятора и кэширования CPU главный цикл for !done {} может никогда не увидеть обновление done = true из другой горутины, и программа зависнет в этом цикле.

Если убрать runtime.GOMAXPROCS(1), то есть позволить планировщику использовать несколько OS-потоков, то вероятность увидеть обновление выше, но не гарантирована без синхронизации.

Правильный способ — использовать каналы или синхронизацию из пакета sync/atomic.

Пример с каналом:

package main

import "fmt"

func main() {
    done := make(chan struct{})
    go func() {
        done <- struct{}{}
    }()
    <-done
    fmt.Println("finished")
}

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее