О процессах, многозадачности, многопроцессорности, потоках и многопоточности

Начинающим разработчикам бывает сложно разобраться в таких темах, как процессы и многозадачность, мультипроцессорность, потоки и многопоточность. Статья разъясняет азы простым языком, без излишней академичности.

Процесс и многозадачность

Процесс — исполняемый экземпляр программы. Когда вы запускаете программу на Python, создается процесс. Пока программа работает, процесс выполняется. Когда программа заканчивает свою работу, процесс завершается.

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

Многозадачность и многопроцессорность

Программа представляет собой последовательность команд. Процессор может выполнять только одну команду за один раз.

Многопроцессорность означает, что несколько процессов могут выполняться одновременно, т. е. в любой момент времени могут выполняться несколько процессов. Это невозможно в системе с одним процессором, потому что процессор может выполнять только одну команду в определенный момент времени. И эта команда может быть связана только с одним процессом, поэтому здесь можно провести сравнение с одним процессом, выполняемым в определенный момент.

Многозадачность означает возможность выполнять два и более процессов одновременно.

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

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

Немного о процессах:

  • Когда процесс запускается, операционная система назначает ему некоторую память.
  • Память не разделяется между различными процессами.

Потоки и многопоточность

Потоки существует в процессе. Таким образом, процесс может иметь несколько потоков. Поток является независимой последовательностью исполнения внутри процесса.

Пример однопоточной программы

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

Простой алгоритм:

  • Пройтись по списку.
  • Получить первый URL.
  • Подождать ответа.
  • Распечатать код ответа.
  • Перейти к следующему URL в списке.
  • Продолжить проход по списку до тех пор, пока не останется ни одного URL.

Получается, что процессор последовательно обходит URL-адреса и не переходит к следующему URL, пока получит ответ от предыдущего.

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

Пример многопоточной программы

  • Создадим пять разных потоков. Каждый поток будет отвечать за один URL.
  • Процессор работает с одним потоком и занимается URL-адресом, связанным с этим потоком.
  • Процессор простаивает, потому что получение ответа занимает некоторое время.
  • Процессор начинает работать над другим потоком и берет в работу URL, связанный с этим потоком. Это происходит до того, как процессор получит ответ от первого URL-адреса.
  • Таким образом, программа не выполняется последовательно и является многопоточной.
  • В какой-то момент приходит ответ для от первого URL и процессор переключается обратно на первый поток и печатает результат.
  • Процессор снова переключается на другой поток.
  • Время простоя процессора в многопоточной версии значительно минимизировано.

Последовательность шагов, описанная здесь, может не соответствовать тому, что в действительности делает процессор, потому что невозможно определить, какой поток когда выполняется.

Потоки с одним и несколькими процессорами

Машина с одним процессором никогда не сможет выполнять фактическую многопроцессорную обработку.

Даже если программа многопоточная, машина с одним процессором может обеспечить, а может и не обеспечить каких-либо преимуществ.

Многопоточная программа будет работать быстрее, чем однопоточная программа на однопроцессорной машине в следующих случаях:

  • Программа предполагает взаимодействие с сетью, т. е. получение ответа от некоторого URL-адреса.
  • Программе требуется ожидать завершения операций ввода-вывода.

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

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

Но если машина имеет несколько процессоров или ядер, многопоточная программа всегда будет работать быстрее, чем однопоточная, потому что разные потоки могут выполняться конкурентно на разных процессорах.


По материалам Akshar Raaj.