Конкурентность и потоки в программировании: краткая история

Конкурентность и потоки в программировании
Илья Дергунов

Илья Дергунов

Автор статьи. ИТ-специалист с 20 летним стажем, автор большого количества публикаций на профильную тематику (разработка ПО, администрирование, новостные заметки). Подробнее.

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

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

Перемены произошли по нескольким причинам:

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

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

Удобство. Зачастую проще написать несколько программ, каждая из которых выполняет одну задачу, и координировать их друг с другом, чем написать единственную программу, выполняющую все задачи.

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

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

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

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

Вас заинтересует / Intresting for you:

Учимся программировать для And...
Учимся программировать для And... 1909 просмотров Валерий Павлюков Sun, 25 Nov 2018, 14:43:29
Android: cохранение данных, ко...
Android: cохранение данных, ко... 1586 просмотров Семен Tue, 05 Mar 2019, 15:40:00
Преимущества потоков в програм...
Преимущества потоков в програм... 1055 просмотров Дэн Mon, 10 May 2021, 08:22:56
Каким образом язык Java измени...
Каким образом язык Java измени... 1961 просмотров Дэн Mon, 05 Nov 2018, 10:42:37
Войдите чтобы комментировать