Конкурентная запись в слайс и роль GOMAXPROCS

Точный результат не определён ни на одном, ни на нескольких ядрах: записи data[1] и чтение без синхронизации образуют гонку данных.

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

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

Точный результат не определён ни на одном, ни на нескольких ядрах: записи data[1] и чтение без синхронизации образуют гонку данных.

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

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

Условие

Определите, какое значение будет напечатано программой при запуске на системе с одним ядром и на системе с несколькими ядрами. Учтите, что несколько горутин одновременно изменяют один и тот же элемент слайса, а планировщик Go распределяет их выполнение в зависимости от текущего значения GOMAXPROCS.

func main() {
    data := make([]string, 0)
    for i := 0; i < 10; i++ {
        data = append(data, string(i))
    }

    go func() { data[1] = "Не знаю" }()
    go func() { data[1] = "Не 1" }()
    go func() { data[1] = "2" }()

    time.Sleep(400 * time.Millisecond)

    fmt.Println(data[1])
}

Ответ

Точный результат не определён ни на одном, ни на нескольких ядрах: записи data[1] и чтение без синхронизации образуют гонку данных.

GOMAXPROCS не устанавливает порядок обращений к памяти и не заменяет mutex или каналы. Sleep также не даёт гарантированного ожидания. Строка имеет многословное представление: такую гонку нельзя описывать лишь как безопасный выбор одного из записанных значений.

Кроме того, string(i) переводит число в Unicode-кодовую точку, а не в десятичную запись. Для строк "0", "1" и далее нужен strconv.Itoa(i). Эти две проблемы исправляются независимо.

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

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

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

Подробнее