Потоки и процессы (Threads & Processes)

Процесс — запущенная программа со своей памятью, поток — ход выполнения внутри процесса; потоки одного процесса делят общую память.

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

Что такое процесс

Когда вы запускаете программу, ядро операционной системы создает процесс: выделяет ему участок оперативной памяти, номер (PID), открытые файлы и сетевые соединения. Память процесса изолирована: другой процесс не может ее прочитать или испортить. Поэтому сбой одной программы обычно не роняет остальные.

Что такое поток

Поток (thread) выполняет команды программы. У каждого потока свой стек и свое место в коде, но память, файлы и соединения процесса у всех потоков общие. Создать поток и переключиться между потоками дешевле, чем между процессами: не нужно выделять и защищать отдельную память.

Чем процесс отличается от потока

Процесс Поток
Память Своя, изолированная Общая с другими потоками процесса
Создание и переключение Дороже Дешевле
Обмен данными Через каналы, сокеты, общую память — средствами ОС Напрямую через общие переменные
Сбой Обычно не затрагивает другие процессы Может обрушить весь процесс
Пример Вкладки браузера Chrome работают в отдельных процессах Веб-сервер обрабатывает запросы пользователей в параллельных потоках

Зачем программе несколько потоков

  • Использовать все ядра. Современный процессор выполняет несколько потоков одновременно, по одному на ядро. Однопоточная программа нагружает лишь одно из них.
  • Не ждать. Пока один поток ждет ответа от базы данных или сети, другие продолжают работу.
  • Отзывчивый интерфейс. Долгая операция идет в фоновом потоке, и окно приложения не «зависает».

Подробнее об одновременном выполнении задач — в термине «Параллелизм».

Проблемы многопоточности

Общая память удобна, но опасна. Два потока одновременно увеличивают общий счетчик со значения 10: оба прочитали 10, оба записали 11 — одно увеличение потерялось. Это гонка состояний (race condition). Если же поток A захватил ресурс 1 и ждет ресурс 2, а поток B держит ресурс 2 и ждет ресурс 1, оба ждут вечно — это взаимная блокировка (deadlock).

Защищаются блокировками (mutex), атомарными операциями и очередями сообщений, через которые потоки обмениваются данными вместо общих переменных. Такие ошибки проявляются редко и случайно, поэтому их сложно воспроизвести — многопоточный код проверяют особенно тщательно, особенно в системах, где важна каждая операция, например в обработке платежей.

У разных языков свои особенности. В стандартном Python (CPython) из-за глобальной блокировки интерпретатора (GIL) код на Python в каждый момент выполняет только один поток, поэтому для вычислительных задач там чаще запускают несколько процессов.

Как посмотреть процессы и потоки

В Linux процессы показывает ps aux или top, а потоки конкретного процесса — команда:

# Командная строка Linux
top -H -p 1234

где 1234 — номер процесса. О командах для работы с системой — в термине Linux CLI. В Windows те же сведения есть в Диспетчере задач на вкладке «Подробности».