> Что такое конкурентность в программировании (Go)
Уровень: junior · Роль: backend · Категория: Технические вопросы
Компании: Моторика
Стек: Go
> Пример ответа
Короткий ответ
Конкурентность - это способность программы выполнять несколько задач одновременно, не дожидаясь завершения каждой. В Go она реализуется через горутины и каналы, что позволяет эффективно использовать ресурсы CPU и обрабатывать множество запросов параллельно. В отличие от параллелизма, конкурентность - это про структуру кода, а не про одновременное выполнение на разных ядрах.
Подробное объяснение
Конкурентность - это композиция независимо выполняющихся вычислений. Программа разбивается на несколько задач, которые могут выполняться в произвольном порядке, частично пересекаясь во времени. Это не то же самое, что параллелизм: параллелизм требует нескольких ядер процессора, а конкурентность - это про логическую структуру.
В Go конкурентность строится на трёх китах:
- горутины - лёгкие потоки, которые управляются рантаймом, а не операционной системой. Стек горутины растёт динамически, а запуск стоит порядка нескольких килобайт памяти;
- каналы - типизированные "трубы" для передачи данных между горутинами. Каналы обеспечивают синхронизацию и безопасный обмен информацией;
- примитивы синхронизации -
sync.Mutex,sync.WaitGroup,sync.Onceи другие для случаев, когда каналы не подходят.
Ключевая идея конкурентности в Go - фраза из документации: "Do not communicate by sharing memory; instead, share memory by communicating". То есть вместо блокировок на общих данных предпочтительнее передавать данные через каналы.
Рантайм Go использует модель M:N - много горутин маппятся на меньшее количество OS-потоков. Планировщик распределяет горутины по потокам, приостанавливая одни и запуская другие. Это позволяет запускать десятки тысяч горутин без деградации производительности.
На практике
В backend-разработке на Go конкурентность применяется повсеместно:
- обработка HTTP-запросов - каждый запрос обрабатывается в отдельной горутине;
- фан-аут/фан-ин - запуск нескольких параллельных операций (например, запросы к разным сервисам) и сбор результатов;
- worker pool - фиксированное число горутин, которые берут задачи из очереди;
- таймауты и отмены через контекст (
context.Context).
Важно помнить про гонки данных (data races) - когда несколько горутин одновременно читают и пишут одну переменную. Для обнаружения используй go run -race. Для защиты - мьютексы или атомики, но чаще лучше пересмотреть дизайн и использовать каналы.
Пример кода
GOpackage mainimport ("fmt""sync""time")func worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {defer wg.Done()for j := range jobs {time.Sleep(100 * time.Millisecond) // имитация работыresults <- j * 2}}func main() {const numJobs = 10const numWorkers = 3jobs := make(chan int, numJobs)results := make(chan int, numJobs)var wg sync.WaitGroup// запускаем воркеровfor w := 1; w <= numWorkers; w++ {wg.Add(1)go worker(w, jobs, results, &wg)}// отправляем задачиfor j := 1; j <= numJobs; j++ {jobs <- j}close(jobs)// ждём завершения всех воркеровwg.Wait()close(results)// собираем результатыfor r := range results {fmt.Println(r)}}
Как отвечать на собеседовании
Начни с определения и сразу разведи конкурентность и параллелизм - это покажет понимание основ. Затем расскажи про горутины и каналы, упомяни, что горутины легче потоков ОС. Приведи пример из практики: обработка запросов или параллельные вызовы API. Если спросят про синхронизацию - упомяни sync.WaitGroup и мьютексы, но подчеркни, что в Go принято отдавать предпочтение каналам. Не углубляйся в детали планировщика, если не просят - для junior достаточно понимания модели.
Что проверяет интервьюер
Интервьюер оценивает:
- понимание разницы между конкурентностью и параллелизмом;
- знание базовых примитивов Go: горутины, каналы,
sync.WaitGroup; - осознание проблем: гонки данных, дедлоки, утечки горутин;
- умение объяснить, когда использовать каналы, а когда мьютексы;
- способность написать простой конкурентный код без ошибок.
Для junior достаточно уверенного ответа на уровне "горутина - это лёгкий поток, канал - для обмена данными". Если упомянешь context.Context и select - это плюс, но не обязательно.
Типичные ошибки
- путать конкурентность с параллелизмом или считать их синонимами;
- говорить, что горутины - это потоки ОС (это не так);
- забывать про гонки данных и не использовать
-race; - использовать
time.Sleepдля синхронизации вместо каналов илиWaitGroup; - закрывать канал из нескольких горутин - это паника;
- не вызывать
wg.Addдо запуска горутин; - игнорировать контекст и отмену операций - в реальном backend это критично.
> Похожие задачи по backend
Какие виды уведомлений используются в системах (SMS, push, email и т.д.)
Какие бывают виды HTTP-запросов и их семантика
Кто ставит задачи и как они распределяются
Как устроен процесс карьерного роста, пересмотра зарплаты и грейдов
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью