В чем разница между конкурентностью и параллелизмом
Что проверяют
Понимаете ли вы, что конкурентность и параллелизм описывают разные вещи: первое это структура программы, второе это способ её исполнения. Следом обычно спрашивают, как это устроено в рантайме Go и станет ли программа быстрее, если запустить в ней тысячу горутин.
Как отвечать
Опорная формулировка из доклада Роба Пайка «Concurrency is not parallelism»: конкурентность это работа с множеством задач сразу, параллелизм это одновременное выполнение множества задач.
- конкурентность: программа разбита на независимые части, которые могут выполняться вперемешку. Это свойство дизайна, оно полезно даже на одном ядре: пока одна горутина ждёт ответа базы, другая обрабатывает запрос;
- параллелизм: несколько частей реально выполняются в один момент на разных ядрах. Это свойство исполнения, без нескольких ядер его нет;
- в Go: горутины распределяет планировщик по модели G-M-P.
GOMAXPROCSзадаёт, сколько потоков ОС одновременно исполняют Go-код. По умолчанию это число доступных ядер, а начиная с Go 1.25 рантайм на Linux учитывает и лимит CPU контейнера из cgroup; - пример: с
GOMAXPROCS=1программа на горутинах и каналах остаётся конкурентной, но перестаёт быть параллельной.
Дальше разведите по типу нагрузки. Для I/O-bound задач (HTTP, база, очереди) выигрыш даёт конкурентность, число ядер почти не важно. Для CPU-bound задач выигрыш даёт только параллелизм, и запускать вычислительных горутин больше, чем ядер, бессмысленно: они будут делить те же ядра и добавят расходы на переключение. Для таких задач обычно делают пул воркеров размером около runtime.NumCPU(), а результаты собирают через канал или errgroup.
Где спотыкаются
Считают, что горутина это поток ОС. Горутина стартует с небольшого стека в несколько килобайт и мультиплексируется на небольшое число потоков, поэтому их можно держать сотни тысяч.
Думают, что больше горутин значит быстрее. Для вычислений ускорение упирается в число ядер, дальше растут только накладные расходы.
Уверены, что на одном ядре гонок данных не бывает. Планировщик вытесняет горутины в любой момент, так что гонки остаются, и искать их нужно через go test -race.