Go: Конкурентность и параллелизм

19 вопросов

1 Чем конкурентность отличается от параллелизма?

Конкурентность - возможность выполнять несколько задач в перекрывающиеся интервалы времени; порядок выполнения может быть чередующимся. Параллелизм - одновременное выполнение на разных ядрах. Конкурентная программа может выполняться на одном ядре (переключение горутин); параллельная - на нескольких.

Открыть отдельно →
2 Что такое deadlock?

Взаимная блокировка: две и более горутин ждут друг друга. Например, A держит Lock1 и ждёт Lock2, B держит Lock2 и ждёт Lock1. Программа не продвигается. В Go детектор может сообщить о deadlock при выходе (если все горутины заблокированы).

Открыть отдельно →
3 Что такое livelock?

Горутины не заблокированы, но не продвигаются - постоянно "отступают" или меняют состояние без результата. Пример: два потока при столкновении оба отступают и снова идут - бесконечный цикл отступлений. Реже встречается, чем deadlock.

Открыть отдельно →
4 Что такое starvation (голодание)?

Горутина долго не получает доступ к ресурсу или CPU из-за других горутин. Например, высокоприоритетные или часто захватывающие мьютекс не дают другим выполниться. В Go планировщик и режим голодания Mutex снижают риск, но не исключают.

Открыть отдельно →
5 Что такое data race?

Одновременный доступ к одной переменной из разных горутин, причём хотя бы один доступ - запись, без синхронизации. Поведение не определено. Обнаруживается тестами с флагом -race. Исправление - синхронизация (каналы, мьютекс, atomic) или отсутствие разделяемого изменяемого состояния.

Открыть отдельно →
6 Как работает детектор гонок (race detector)?

При сборке с -race компилятор и рантайм инструментируют доступ к памяти. Во время выполнения отслеживают happens-before и обнаруживают конфликтующие доступы. Выводят отчёт о гонке при обнаружении. Существенные накладные расходы по памяти и скорости - только для тестов и отладки.

go test -race
go run -race ./cmd
Открыть отдельно →
7 Как избежать deadlock?

Единый порядок захвата блокировок (всегда сначала Lock1, потом Lock2). Избегать удержания нескольких блокировок; брать только нужную. Использовать таймауты (TryLock, select с time.After). По возможности - каналы и один владелец данных вместо нескольких мьютексов.

Открыть отдельно →
8 Что такое lock-free структуры данных?

Структуры, которые не используют блокировки (мьютексы), а полагаются на атомарные операции (CAS, LL/SC) и повторные попытки. Могут дать лучшую масштабируемость при высокой конкуренции. Сложнее в реализации и отладке. В Go - через sync/atomic или пакеты вроде sync.Map.

Открыть отдельно →
9 Что такое модель CSP?

Communicating Sequential Processes: процессы (горутины) общаются только через передачу сообщений (каналы), без разделяемой памяти. "Don't communicate by sharing memory; share memory by communicating." В Go каналы - первый способ координации; мьютексы - для случаев, когда разделяемая память нужна.

Открыть отдельно →
10 Что такое проблема ABA?

В lock-free структурах: значение A меняется на B и снова на A. Поток, делающий CAS "если всё ещё A", считает что ничего не изменилось, хотя между ними могли быть другие изменения. Решение - версионирование или tag. В Go реже встречается при использовании atomic.Value и аккуратном проектировании.

Открыть отдельно →
11 Что такое CAS (Compare-And-Swap)?

Атомарная операция: если текущее значение равно ожидаемому, записать новое и вернуть true; иначе не менять и вернуть false. В Go: atomic.CompareAndSwapInt32, CompareAndSwapInt64 и т.д. Основа для lock-free алгоритмов и спинлоков.

for !atomic.CompareAndSwapInt64(&n, old, new) { old = atomic.LoadInt64(&n) }
Открыть отдельно →
12 Почему map не потокобезопасна? Data race на map.

Встроенная map не защищена от конкурентной записи и одновременной записи и чтения. Одновременная запись и чтение или две записи - data race и возможный крах. Решение: sync.Mutex при доступе к map или sync.Map для специфичных паттернов доступа.

var mu sync.Mutex
mu.Lock(); m[k] = v; mu.Unlock()
Открыть отдельно →
13 Каналы vs разделяемые переменные?

Каналы - передача владения данными, явные точки синхронизации, модель CSP. Разделяемые переменные с мьютексом - общая память с блокировкой. Каналы подходят для pipeline и передачи данных; мьютекс - для защиты общего состояния. Часто каналы проще рассуждать.

Открыть отдельно →
14 Что такое happens-before?

Отношение порядка между событиями в программе. Если A happens-before B, то A видно для B. Синхронизация (канал, мьютекс, atomic) создаёт happens-before между горутинами. Memory model Go определяет, какие наблюдения допустимы при заданной синхронизации.

Открыть отдельно →
15 Что такое memory ordering?

Порядок видимости операций с памятью между ядрами. Компилятор и процессор могут переупорядочивать операции; барьеры и атомарные операции ограничивают переупорядочивание. В Go sync/atomic даёт нужные гарантии; обычные чтения/записи не гарантируют порядок между горутинами без синхронизации.

Открыть отдельно →
16 Что такое false sharing?

Несколько горутин обращаются к разным переменным, но они попадают в одну кеш-линию. Обновление одной переменной инвалидирует кеш-линию у других ядер - лишние промахи кеша и падение производительности. Решение: выравнивание и паддинг, чтобы горячие данные разных горутин были в разных кеш-линиях.

Открыть отдельно →
17 Как сделать потокобезопасный счётчик?

Через atomic: atomic.AddInt64, LoadInt64, StoreInt64. Либо мьютекс и обычная переменная. atomic быстрее при высокой конкуренции для одной переменной.

var counter int64
atomic.AddInt64(&counter, 1)
n := atomic.LoadInt64(&counter)
Открыть отдельно →
18 Race condition vs data race?

Data race - неопределённое поведение из-за одновременного доступа к памяти без синхронизации (баг). Race condition - логическая ошибка: результат зависит от порядка выполнения горутин, даже при корректной синхронизации (например, проверка и затем действие без атомарности). Оба - источники сбоев.

Открыть отдельно →
19 Обнаруживает ли runtime deadlock в Go?

Да. Если при завершении программы все горутины заблокированы (ждут канал или блокировку), рантайм может вывести "fatal error: all goroutines are asleep - deadlock!". Не все deadlock'и обнаруживаются (например, если есть горутины в select с несколькими case).

Открыть отдельно →
🧠Квиз 🏆Лидеры 🎯Собесед. 📖Вопросы 📚База зн.