C Thread - это что такое? Отличие от процессов. Примеры реализаций потоков на уровне пользователя

Потоки (threads) и многопоточное выполнение программ (multi-threading)

Однопоточные и многопоточные процессы

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

Рис. 11. Однопоточный и многопоточный процессы.

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

Многопоточность имеет большие преимущества:

  • Увеличение скорости (по сравнению с использованием обычных процессов). Многопоточность основана на использовании облегченных процессов (lightweight processes) ,работающих в общем пространстве виртуальной памяти. Благодаря многопоточности, не возникает больше неэффективных ситуаций, типичных для классической системы UNIX.
  • Использование общих ресурсов . Потоки одного процесса используют общую память и файлы.
  • Экономия . Благодаря многопоточности, достигается значительная экономия памяти, по причинам, объясненным выше. Также достигается и экономия времени, так как переключение контекста на облегченный процесс, для которого требуется только сменить стек и восстановить значения регистров, значительно быстрее, чем на обычный процесс.

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



Пользовательские потоки и потоки ядра

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

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

  • Windows 95/98/NT/2000/XP/2003/2008/7;
  • Solaris;
  • Tru64 UNIX;
  • BeOS;
  • Linux.

Существуют различные модели многопоточности – способы отображения пользовательских потоков в потоки ядра. Теоретически возможны (и на практике реализованы) следующие модели многопоточности:

Модель много / один (many-to-one) – отображение нескольких пользовательских потоков в один и тот же поток ядра. Используется в операционных системах, не поддерживающих множественные системные потоки (например, с целью экономии памяти). Данная модель изображена на рис. 2.

Рис. 10.2. Схема модели многопоточности "много / один".

Модель один / один (one-to-one) – взаимно-однозначное отображение каждого пользовательского потока в определенный поток ядра. Примеры ОС, использующих данную модель, - Windows 95/98/NT/2000/XP/2003/2008/7; OS/2. Данная модель изображена на рис. 3.

Рис. 10.3. Схема модели многопоточности "один / один".

Модель много / много (many-to-many) – модель, допускающая отображение нескольких пользовательских потоков в несколько системных потоков. Такая модель позволяет ОС создавать большое число системных потоков. Характерным примером ОС, использующей подобную модель, является ОС Solaris, а также Windows NT / 2000 / XP / 2003 / 2008 / 7 с пакетом ThreadFiber . Данная модель изображена на рис. 4.

Рис. 4. Схема модели многопоточности "много / много".

Потоки в Windows 2000

Как уже отмечалось, в системе Windows реализована модель многопоточности "один / один". Каждый поток содержит:

  • идентификатор потока (thread id);
  • набор регистров
  • отдельные стеки для пользовательских и системных процедур;
  • область памяти для локальных данных потока (thread-local storage – TLS).

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

Многопоточность – весьма сложная, еще не полностью изученная и, тем более, не полностью формализованная область, в которой имеется много интересных проблем. Рассмотрим некоторые из них.

Семантика системных вызовов fork() и exec() .Как уже отмечалось, в классической ОС UNIX системный вызов fork создает новый "тяжеловесный" процесс со своим адресным пространством, что значительно "дороже", чем создание потока. Однако, с целью поддержания совместимости программ снизу вверх, приходится сохранять эту семантику, а многопоточность вводить с помощью новых системных вызовов.

Прекращение потоков . Важной проблемой является проблема прекращения потоков: например, если родительский поток прекращается, то должен ли при этом прекращаться дочерний поток? Если прекращается стандартный процесс, создавший несколько потоков, то должны ли прекращаться все его потоки? Ответы на эти вопросы в разных ОС неоднозначны.

Обработка сигналов . Сигналы в UNIX – низкоуровневый механизм обработки ошибочных ситуаций. Примеры сигналов: SIGSEGV - нарушение сегментации (обращение по неверному адресу, чаще всего по нулевому); SIGKILL – сигнал процессу о выполнении команды kill его уничтожения. Пользователь может определить свою процедуру-обработчик сигнала системным вызовом signal . Проблема в следующем: как распространяются сигналы в многопоточных программах и каким потоком они должны обрабатываться? В большинстве случаев этот вопрос решается следующим образом: сигнал обрабатывается потоком, в котором он сгенерирован, и влияет на исполнение только этого потока. В более современных ОС (например, Windows 2000 и более поздних версиях Windows), основанных на объектно-ориентированной методологии, концепция сигнала заменена более высокоуровневой концепцией исключения (exception) .Исключение распространяется по стеку потока в порядке, обратном порядку вызовов методов, и обрабатывается первым из них, в котором система находит подходящий обработчик. Аналогичная схема обработки исключений реализована в Java и в.NET.

Группы потоков . В сложных задачах, например, задачах моделирования, при большом числе разнородных потоков, возникает потребность в их структурировании и помощью концепции группы потоков – совокупности потоков, имеющей свое собственное имя, над потоками которой определены групповые операции. Наиболее удачно, с нашей точки зрения, группы потоков реализованы в Java (с помощью класса ThreadGroup ). Следует отметить также эффективную реализацию пулов потоков (ThreadPool) в.NET.

Локальные данные потока (thread-local storage - TLS) – данные, принадлежащие только определенному потоку и используемые только этим потоком. Необходимость в таких данных очевидна, так как многопоточность – весьма важный метод распараллеливания решения большой задачи, при котором каждый поток работает над решением порученной ему части. Все современные операционные системы и платформы разработки программ поддерживают концепцию локальных данных потока.

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

Тупики (deadlocks) и их предотвращение . Как и процессы, потоки могут взаимно блокировать друг друга (т.е. может создаться ситуация deadlock ), при их неаккуратном программировании.

42. Файловые системы. Обзор.

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

Файловая система – это набор спецификаций и соответствующее им программное обеспечение, которые отвечают за создание, уничтожение, организацию, чтение, запись, модификацию и перемещение файловой информации, а также за управление доступом к файлам и за управление ресурсами, которые используются файлами. Именно файловая система определяет способ организации данных на диске или на каком-нибудь ином носителе данных. В качестве примера можно привести файловую систему FAT, реализация для которой имеется в абсолютном большинстве ОС, работающих в современных ПК1.

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

  • ♦ создание, удаление, переименование (и другие операции) именованных наборов данных (именованных файлов) из своих программ или посредством специальных управляющих программ, реализующих функции интерфейса пользователя с его данными и активно использующих систему управления файлами;
  • ♦ работа с не дисковыми периферийными устройствами как с файлами;
  • ♦ обмен данными между файлами, между устройствами, между файлом и уст-

ройством (и наоборот);

  • ♦ работа с файлами с помощью обращений к программным модулям системы

управления файлами (часть API ориентирована именно на работу с файлами);

  • ♦ защита файлов от несанкционированного доступа.

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

Другими словами, термин «файловая система» определяет, прежде всего,

принципы доступа к данным, организованным в файлы. Этот же термин часто ис-

пользуют и по отношению к конкретным файлам, расположенным на том или ином

носителе данных. А термин «система управления файлами» следует употреблять

по отношению к конкретной реализации файловой системы, то есть это – комплекс

программных модулей, обеспечивающих работу с файлами в конкретной операци-

онной системе.

Следует ещё раз заметить, что любая система управления файлами не сущест-

вует сама по себе – она разработана для работы в конкретной ОС. В качестве при-

мера можно сказать, что всем известная файловая система FAT (file allocation table)

имеет множество реализации как система управления файлами. Так, система, полу-

чившая это название и разработанная для первых персональных компьютеров, на-

зывалась просто FAT (сейчас её называют FAT-12). Её разрабатывали для работы с

дискетами, и некоторое время она использовалась при работе с жесткими дисками.

Потом её усовершенствовали для работы с жесткими дисками большего объёма, и

эта новая реализация получила название FAT-16. Это название файловой системы

мы используем и по отношению к системе управления файлами самой MS-DOS.

Реализацию же системы управления файлами для OS/2, которая использует основ-

ные принципы системы FAT, называют super-FAT; основное отличие – возмож-

ность поддерживать для каждого файла расширенные атрибуты. Есть версия системы управления файлами с принципами FAT и для Windows 95/98, для Windows

NT и т. д. Другими словами, для работы с файлами, организованными в соответствии с некоторой файловой системой, для каждой ОС должна быть разработана соответствующая система управления файлами. Эта система управления файлами будет работать только в той ОС, для которой она и создана; но при этом она позволит работать с файлами, созданными с помощью системы управления файлами другой ОС, работающей по тем же основным принципам файловой системы.

Файловая система FAT

Как мы уже отмечали, аббревиатура FAT (file allocation table) расшифровывается как «таблица размещения файлов». Этот термин относится к линейной табличной структуре со сведениями о файлах – именами файлов, их атрибутами и другими данными,

определяющими местонахождение файлов (или их фрагментов) в среде FAT. Элемент FAT определяет фактическую область диска, в которой хранится начало физического файла. В файловой системе FAT логическое дисковое пространство любого логиче-

ского диска делится на две области (рис. 4.6): системную область и область дан-

Рис.4.6. Структура логического диска

R | Sec | Fat1 | Fat2 | Dir | Каталоги и файлы

________________________________________________________

Системная область | Область данных

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

Загрузочной записи (boot record, BR);

Зарезервированных секторов (reserved sector, ResSecs);

Таблицы размещения файлов (file allocation table, FAT);

Корневого каталога (root directory, RDir).

Таблица размещения файлов

Таблица размещения файлов является очень важной информационной структурой. Можно сказать, что она представляет собой карту (образ) области данных, в которой описывается состояние каждого участка области данных. Область данных разбивают на так называемые кластеры. Кластер представляет собой один или несколько смежных секторов в логическом дисковом адресном пространстве (точнее – только в области данных). В таблице FAT кластеры, принадлежащие одному файлу (некорневому каталогу), связываются в цепочки. Для указания номера кластера и системе управления файлами FAT-16 используется 16-битовое слово, следовательно, можно иметь до 216 = 65536 кластеров (с номерами от 0 до 65535). Кластер – это минимальная адресуемая единица дисковой памяти, выделяемая файлу (или некорневому каталогу). Файл или каталог занимает целое число кластеров. Последний кластер при этом может быть задействован не полностью, что приведет к заметной потере дискового пространства при большом размере кластера. На дискетах кластер занимает один или два сектора, а на жёстких дисках – в зависимости от объёма раздела.

FAT32 - последняя версия файловой системы FAT и улучшение предыдущей версии, известной как FAT16. Она была создана, чтобы преодолеть ограничения на размер тома в FAT16, позволяя при этом использовать старый код программ MS-DOS и сохранив формат. FAT32 использует 32-разрядную адресацию кластеров. FAT32 появилась вместе с Windows 95 OSR2.

NTFS (от англ. New Technology File System - «файловая система новой технологии») - стандартная файловая система для семейства операционных систем Microsoft Windows NT.

NTFS заменила использовавшуюся в MS-DOS и Microsoft Windows файловую систему FAT. NTFS поддерживает системуметаданных

И использует специализированные структуры данных для хранения информации о файлах для улучшения производительности, надёжности и эффективности использования дискового пространства. NTFS хранит информацию о файлах в главной файловой таблице - Master File Table (MFT). NTFS имеет встроенные возможности разграничивать доступ к данным для различных пользователей и групп пользователей (списки контроля доступа - Access Control Lists (ACL)), а также назначать квоты (ограничения на максимальный объём дискового пространства, занимаемый теми или иными пользователями). NTFS использует систему журналирования USN для повышения надёжности файловой системы.

43. Управление памятью в операционной системе. Типы адресов.

Основную (оперативную) память компьютерной системы можно рассматривать как большой массив слов или байтов, каждый из которых имеет свой адрес. Память - это хранилище данных с быстрым доступом, совместно используемое процессором и устройствами ввода-вывода.

Следует иметь в виду важную особенность основной памяти. В компьютерных архитектурах имеется два различных способа нумерации байтов в слове. По традиции будем представлять себе память как линейный массив, расположенный "слева направо", такой, что адреса слов, находящихся левее, меньше, чем адреса слов, находящихся правее. Каждое слово делится на байты, имеющие в слове свои номера – 0, 1 и т.д.. Например, в 64-разрядных системах в слове 8 байтов, с номерами от 0 до 7, в более старых 16-разрядных (x86) – два байта, с номерами 0 и 1. Если нумерация байтов в слове начинается слева, т.е. начиная со старших битов, то такую архитектуру принято называть big endian , если же справа, т.е. начиная с младших битов, то little endian. Например, при big endian – архитектуре 32-разрядного процессора байты двух соседних слов памяти нумеруются так: 0, 1, 2, 3, 0, 1, 2, 3. При little endian же архитектуре нумерация будет иной: 3, 2, 1, 0, 3, 2, 1, 0. Представим теперь, что мы хотим рассматривать эти же два слова как массив байтов длиной 8 и записать туда байт за байтом символы строки: "ЭТОТЕКСТ" (всего – 8 символов). Такая операция при обеих архитектурах будет выполнена одинаково, т.е. последовательные байты получат именно эти значения. Затем рассмотрим результат снова, но уже как последовательность их двух слов. Каково будет содержимое этих слов? При big endian – архитектуре сюрпризов не будет: первое слово – "ЭТОТ", второе "ЕКСТ". Однако при little endian – архитектуре результат будет совсем иным: первое слово – "ТОТЭ", второе – "ТСКЕ" ! Не забудем, что при обработке целого слова в little endian – архитектуре байты как бы "переставляются" в обратном порядке. Разумеется, это неудобно. С подобной проблемой автор столкнулся при переносе написанного им компилятора с архитектуры SPARC (big endian) на архитектуру Intel x86 (little endian), используя типы byte и word на Турбо-Паскале. Подобная операция типична для системных программ, например, таблица идентификаторов в компиляторе должна содержать как символы идентификатора (последовательность байтов), так и другую информацию о нем (длину, ссылки в различные таблицы и т.д.). Поэтому при little endian – архитектуре приходится хранить и обрабатывать байтовые массивы и массивы слов отдельно, и нельзя изменять точку зрения на одну и ту же область памяти и рассматривать ее то как массив байтов, то как массив слов.

Пример little endian – архитектуры – x86. Пример big endian – архитектуры – SPARC. При программировании на языках высокого уровня разработчику, как правило, не приходится учитывать это различие. Однако если при реализации распределения памяти требуется одну и ту же область памяти рассматривать то как массив слов, то как массив байтов, то для little endian – архитектур могут быть "сюрпризы", связанные с тем, что при записи в память как в массив слов байты как бы переставляются.

Основная память – это неустойчивое (volatile ) устройство памяти. Ее содержимое теряется при сбое системы или при выключении питания. Для организации устойчивой памяти используются другие, более медленные технологии.

ОС отвечает за следующие действия, связанные с управлением памятью:

  • Отслеживание того, какие части памяти в данный момент используются и какими процессами . Как правило, ОС организует для каждого процесса свою виртуальную память – расширение основной памяти путем хранения ее образа на диске и организации подкачки в основную память фрагментов (страниц или сегментов) виртуальной памяти процесса и ее откачки по мере необходимости.
  • Стратегия загрузки процессов в основную память, по мере ее освобождения . При активизации процесса и его запуске или продолжении его выполнения процесс должен быть загружен в основную память, что и осуществляется операционной системой. При этом, возможно, какие-либо не активные в данный момент процессы приходится откачивать на диск.
  • Выделение и освобождение памяти по мере необходимости . ОС обслуживает запросы вида "выделить область основной памяти длиной n байтов" и "освободить область памяти, начинающуюся с заданного адреса, длиной m байтов". Длина участков выделяемой и освобождаемой памяти может быть различной. ОС хранит список занятой и свободной памяти. При интенсивном использовании памяти может возникнуть ее фрагментация – дробление на мелкие свободные части, вследствие того, что при запросах на выделение памяти длина найденного сегмента оказывается немного больше, чем требуется, и остаток сохраняется в списке свободной памяти как область небольшого размера (подчас всего 1 – 2 слова). В курсе рассмотрены различные стратегии управления памятью и борьбы с фрагментацией. При исчерпании основной памяти ОС выполняет сборку мусора – поиск не используемых фрагментов, на которые потеряны ссылки, и уплотнение (компактировку) памяти – сдвиг всех используемых фрагментов по меньшим адресам, с корректировкой всех адресов.

Типы адресов

Для идентификации переменных и команд используются символьные имена (метки), виртуальные адреса и физические адреса (рисунок 2.7).
Символьные имена присваивает пользователь при написании программы на алгоритмическом языке или ассемблере.
Виртуальные адреса вырабатывает транслятор, переводящий программу на машинный язык. Так как во время трансляции в общем случае не известно, в какое место оперативной памяти будет загружена программа, то транслятор присваивает переменным и командам виртуальные (условные) адреса, обычно считая по умолчанию, что программа будет размещена, начиная с нулевого адреса. Совокупность виртуальных адресов процесса называется виртуальным адресным пространством. Каждый процесс имеет собственное виртуальное адресное пространство. Максимальный размер виртуального адресного пространства ограничивается разрядностью адреса, присущей данной архитектуре компьютера, и, как правило, не совпадает с объемом физической памяти, имеющимся в компьютере.

Рис. 2.7. Типы адресов

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

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

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

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

Все методы управления памятью могут быть разделены на два класса: методы, которые используют перемещение процессов между оперативной памятью и диском, и методы, которые не делают этого (рисунок 2.8). Начнем с последнего, более простого класса методов.

Рис. 2.8. Классификация методов распределения памяти

Пото́к выполне́ния (тред; от англ. thread - нить) - наименьшая единица обработки, исполнение которой может быть назначено ядром операционной системы . Реализация потоков выполнения и процессов в разных операционных системах отличается друг от друга, но в большинстве случаев поток выполнения находится внутри процесса. Несколько потоков выполнения могут существовать в рамках одного и того же процесса и совместно использовать ресурсы, такие как память , тогда как процессы не разделяют этих ресурсов. В частности, потоки выполнения разделяют инструкции процесса (его код) и его контекст (значения переменных, которые они имеют в любой момент времени). В качестве аналогии потоки выполнения процесса можно уподобить нескольким вместе работающим поварам. Все они готовят одно блюдо, читают одну и ту же кулинарную книгу с одним и тем же рецептом и следуют его указаниям, причём не обязательно все они читают на одной и той же странице.

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

Многие современные операционные системы поддерживают как временные нарезки от планировщика процессов, так и многопроцессорные потоки выполнения. Ядро операционной системы позволяет программистам управлять потоками выполнения через интерфейс системных вызовов . Некоторые реализации ядра называют потоком ядра , другие же - легковесным процессом (англ. light-weight process , LWP), представляющим собой особый тип потока выполнения ядра, который совместно использует одни и те же состояния и данные.

Программы могут иметь пользовательское пространство потоков выполнения при создании потоков с помощью таймеров, сигналов или другими методами, позволяющими прервать выполнение и создать временную нарезку для конкретной ситуации (Ad hoc).

Энциклопедичный YouTube

  • 1 / 5

    Потоки выполнения отличаются от традиционных процессов многозадачной операционной системы тем, что:

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

    Многопоточность

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

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

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

    Операционные системы планируют выполнение потоков одним из двух способов:

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

    До конца 1990-х процессоры в настольных компьютерах не имели поддержки многопоточности, так как переключение между потоками, как правило, происходило быстрее, чем полное переключение контекста процесса. Процессоры во встраиваемых системах , которые имеют более высокие требования к поведению в реальном времени , могут поддерживать многопоточность за счёт уменьшения времени на переключение между потоками, возможно, путём распределения выделенных регистровых файлов для каждого потока выполнения, вместо сохранения/восстановления общего регистрового файла. В конце 1990-х идея выполнения инструкций нескольких потоков одновременно, известная как одновременная многопоточность, под названием Hyper-Threading, достигла настольных компьютеров с процессором Intel Pentium 4 . Потом она была исключена из процессоров архитектуры Intel Core и Core 2 , но позже восстановлена в архитектуре Core i7 .

    Критики многопоточности утверждают, что увеличение использования потоков имеет существенные недостатки:

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

    Процессы, потоки выполнения ядра, пользовательские потоки и файберы

    Процесс является «самой тяжёлой» единицей планирования ядра. Собственные ресурсы для процесса выделяются операционной системой. Ресурсы включают память, дескрипторы файлов, разъёмы, дескрипторы устройств и окна. Процессы используют адресное пространство и файлы ресурсов в режиме разделения времени только через явные методы, такие как наследование дескрипторов файлов и сегментов разделяемой памяти. Процессы, как правило, предварительно преобразованы к многозадачному способу выполнения.

    Потоки выполнения ядра относятся к «лёгким» единицам планирования ядра. Внутри каждого процесса существует по крайней мере один поток выполнения ядра. Если в рамках процесса могут существовать несколько потоков выполнения ядра, то они совместно используют общую память и файл ресурсов. Если процесс выполнения планировщика операционной системы является приоритетным, то потоки выполнения ядра тоже являются приоритетно многозадачными. Потоки выполнения ядра не имеют собственных ресурсов, за исключением стека вызовов , копии регистров процессора , включая счётчик команд , и локальную память потока выполнения (если она есть). Ядро может назначить по одному потоку выполнения для каждого логического ядра системы (поскольку каждый процессор разделяет сам себя на несколько логических ядер, если он поддерживает многопоточность, либо поддерживает только одно логическое ядро на каждое физическое ядро, если не поддерживает многопоточность), а может выполнять свопинг заблокированных потоков выполнения. Однако потоки выполнения ядра требуют гораздо больше времени, чем требуется на свопинг пользовательских потоков выполнения.

    Потоки выполнения иногда реализуются в пользовательском пространстве библиотек, в этом случае они называются пользовательскими потоками выполнения . Ядро не знает о них, так что они управляются и планируются в пользовательском пространстве. В некоторых реализациях пользовательские потоки выполнения основываются на нескольких верхних потоках выполнения ядра , чтобы использовать преимущества многопроцессорных машин (модели M:N). В данной статье под термином «поток выполнения» по умолчанию (без квалификатора «ядра» или «пользовательский») имеется в виду «поток выполнения ядра». Пользовательские потоки выполнения, реализованные с помощью виртуальных машин , называют также «зелёными потоками выполнения». Пользовательские потоки выполнения, как правило, можно быстро создавать, и ими легко управлять, но они не могут использовать преимущества многопоточности и многопроцессорности. Они могут блокироваться, если все связанные с ним потоки выполнения ядра заняты, даже если некоторые пользовательские потоки готовы к запуску.

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

    Проблемы потоков выполнения и файберов

    Параллелизм и структуры данных

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

    Чтобы избежать этого, прикладные программные интерфейсы (API) потоков выполнения предлагают примитивы синхронизации , такие как мьютексы , для блокировки структур данных от одновременного доступа. На однопроцессорных системах поток выполнения, обратившийся к заблокированному мьютексу, должен остановить работу и, следовательно, инициировать переключение контекста. На многопроцессорных системах поток выполнения может вместо опроса мьютекса произвести захват спинлока . Оба этих способа могут снижать производительность и вынуждать процессор в SMP-системах конкурировать за шину памяти, особенно если уровень модульности блокировок слишком высокий.

    Ввод-вывод и планирование

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

    Однако использование блокировок системных вызовов для пользовательских потоков выполнения (в отличие от потоков выполнения ядра) и файберов имеет свои проблемы. Если пользовательский поток выполнения или файбер выполняет системный вызов, другие потоки выполнения и файберы процесса не могут работать до завершения этой обработки. Типичный пример такой проблемы связан с выполнением операций ввода-вывода. Большинство программ рассчитаны на синхронное выполнение ввода-вывода. При инициации ввода-вывода делается системный вызов, и он не возвращается до его завершения. В промежутке весь процесс блокируется ядром и не может исполняться, лишая возможности работы другие пользовательские потоки и файберы этого процесса.

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

    N:1 (потоки выполнения уровня пользователя)

    В модели N:1 предполагается, что все потоки выполнения уровня пользователя отображаются на единую планируемую сущность уровня ядра, и ядро ничего не знает о составе прикладных потоков выполнения. При таком подходе переключение контекста может быть сделано очень быстро, и, кроме того, он может быть реализован даже на простых ядрах, которые не поддерживают многопоточность. Однако, одним из главных недостатков его является то, что в нём нельзя извлечь никакой выгоды из аппаратного ускорения на многопоточных процессорах или многопроцессорных компьютерах, потому что только один поток выполнения может быть запланирован на любой момент времени. Эта модель используется в GNU Portable Threads.

    M:N (смешанная потоковость)

    В модели M:N некоторое число M прикладных потоков выполнения отображаются на некоторое число N сущностей ядра или «виртуальных процессоров». Модель является компромиссной между моделью уровня ядра («1:1») и моделью уровня пользователя («N:1»). Вообще говоря, «M:N» потоковость системы являются более сложной для реализации, чем ядро или пользовательские потоки выполнения, поскольку изменение кода как для ядра, так и для пользовательского пространства не требуется. В M:N реализации библиотека потоков отвечает за планирование пользовательских потоков выполнения на имеющихся планируемых сущностях. При этом переключение контекста потоков делается очень быстро, поскольку модель позволяет избежать системных вызовов. Тем не менее, увеличивается сложность и вероятность инверсии приоритетов, а также неоптимальность планирования без обширной (и дорогой) координации между пользовательским планировщиком и планировщиком ядра.

    POSIX Threads

    Примеры реализаций смешанных потоков

    • «Scheduler activations» используется в собственной библиотеке приложений потоков POSIX для NetBSD (модель M:N в противоположность модели 1:1 ядра или модели приложений пользовательского пространства)
    • Marcel из проекта PM2
    • ОС для суперкомпьютера Tera/Cray MTA

    Примеры реализаций файберов

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

    …). Некоторые языки разрабатываются специально для параллелизма (Ateji PX, CUDA).

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

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

    • POSIX Pthreads – потоки, специфицированные стандартом POSIX и используемые в POSIX-приложениях (рассмотрены позже в данной лекции);
    • Mac C-threads – пользовательские потоки в системе MacOS;
    • Solaris threads – пользовательские потоки в ОС Solaris (рассмотрены позже в данной лекции).

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

    • Windows 95/98/NT/2000/XP/2003/2008/7;
    • Solaris;
    • Tru64 UNIX;
    • BeOS;
    • Linux.

    Существуют различные модели многопоточности – способы отображения пользовательских потоков в потоки ядра. Теоретически возможны (и на практике реализованы) следующие модели многопоточности:

    Модель много / один (many-to-one) – отображение нескольких пользовательских потоков в один и тот же поток ядра. Используется в операционных системах, не поддерживающих множественные системные потоки (например, с целью экономии памяти). Данная модель изображена на рис. 10.2 .

    Рис. 10.2. Схема модели многопоточности "много / один".

    Модель один / один (one-to-one) – взаимно-однозначное отображение каждого пользовательского потока в определенный поток ядра. Примеры ОС, использующих данную модель, - Windows 95/98/NT/2000/XP/2003/2008/7; OS/2. Данная модель изображена на рис. 10.3 .

    Рис. 10.3. Схема модели многопоточности "один / один".

    Модель много / много (many-to-many) – модель, допускающая отображение нескольких пользовательских потоков в несколько системных потоков. Такая модель позволяет ОС создавать большое число системных потоков. Характерным примером ОС, использующей подобную модель, является ОС Solaris, а также Windows NT / 2000 / XP / 2003 / 2008 / 7 с пакетом ThreadFiber . Данная модель изображена на рис. 10.4 .

    Рис. 10.4. Схема модели многопоточности "много / много".

    Конец работы -

    Эта тема принадлежит разделу:

    В лекции рассматриваются понятие потока thread и многопоточное выполнение multi-threading

    В лекции рассматриваются понятие потока thread и многопоточное выполнение multi threading модели многопоточности пользовательские потоки и.. содержание введение однопоточные и многопоточные процессы история многопоточности пользовательские..

    Если Вам нужно дополнительный материал на эту тему, или Вы не нашли то, что искали, рекомендуем воспользоваться поиском по нашей базе работ:

    Что будем делать с полученным материалом:

    Если этот материал оказался полезным ля Вас, Вы можете сохранить его на свою страничку в социальных сетях:

    Все темы данного раздела:

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

    История многопоточности
    Как небезынтересно отметить, один из первых шагов на пути к широкому использованию многопоточности, по-видимому, был сделан в 1970-е годы советскими разработчиками компьютерной аппаратуры и програм

    Проблемы многопоточности
    Многопоточность – весьма сложная, еще не полностью изученная и, тем более, не полностью формализованная область, в которой имеется много интересных проблем. Рассмотрим некоторые из них.

    Потоки и процессы в Solaris
    В ОС Solaris, как уже было отмечено, используется модель потоков много / много. Кроме того, в системе используется также уже известное нам понятие облегченный процесс (ligh

    Потоки в Java
    Как уже отмечалось, Java – первая платформа для разработки программ, в которой многопоточность поддержана на уровне языка и базовых библиотек. Потоки в Java могут быть созданы следующими способами:

    Ключевые термины
    Mac C-threads – пользовательские потоки в системе MacOS. POSIX Pthreads – потоки, специфицированные стандартом POSIX и используемые в POSIX-приложениях. Solaris threads – пользова

    Модель много / много- модель многопоточности,при которой различные пользовательские потокимогут быть отображены в различные потоки ядра
    Модель много / один- модель многопоточности, при которой несколько пользовательских потоковмогут быть отображены в один поток ядра

    Краткие итоги
    Многопоточность (multi-threading) – современное направление программирования, особенно актуальное в связи с широким распространением параллельных компьютерных архитектур. Поток – особый вид процесс

    Вопросы
    Что такое поток? Чем отличаются однопоточные и многопоточные процессы? В чем преимущества многопоточности? В какой системе впервые было реализовано понятие процесса

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

    Темы для курсовых работ, рефератов, эссе
    История концепции потока и многопоточности в операционных системах и языках программирования (реферат). Обзор многопоточности в UNIX, Linux, Solaris (реферат). Обзор многопо

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

    Вы можете:

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

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

    Поток сайта и пользовательский поток – это не одно и то же

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

    Поток сайта – это как взгляд на карту территории. Карта показывает вам всё, с высоты птичьего полета, и задает общее направление. Этот высокоуровневый обзор, позволяет вам почувствовать весь размер, и всю сложность сайта.

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

    Когда нужно использовать поток сайта

    Прежде, чем начать заниматься ваерфрэймами, важно определиться с тем, какие страницы попадут на сайт. Затем, нужно определить какие страницы будут друг на друга ссылаться. Это позволит вам создать СТА, которые будут проводить пользователя по правильному страничному потоку.

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

    Что общего у футболки и компьютерной программы? Они обе состоят из многих потоков! В то время как нитки в футболке держат ткань в виде единого полотна, C Thread (в буквальном смысле — «нити» или «потоки») операционной системы объединяют все программы, для того чтобы выполнить последовательные или параллельные действия одновременно. Каждый поток в программе идентифицирует процесс, который запускается, когда система (system Thread C) запрашивает его. Это оптимизирует работу такого сложного устройства как персональный компьютер и положительно сказывается на его быстродействии и производительности.

    Определение

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

    Для потоков обычно задается определенный приоритет, что означает, что некоторые потоки имеют приоритет над другими. Как только процессор завершит обработку одного потока, он может запустить следующий, ожидающий очереди. Как правило, ожидание не превышает нескольких миллисекунд. Компьютерные программы, реализующие «многопоточность», могут выполнять сразу несколько потоков. Большинство современных ОС поддерживают С Thread на системном уровне. Это означает, что когда одна программа пытается забрать все ресурсы процессора, система принудительно переключается на другие программы и заставляет программу поддержки процессора разделять ресурсы равномерно.

    Термин «поток» (С Thread) также может ссылаться на серию связанных сообщений в онлайн-обсуждении. Веб-доски объявлений состоят из множества тем или веток. Ответы, отправленные в ответ на исходную публикацию, являются частью одного и того же потока. В электронной почте поток может ссылаться на серию ответов в виде команд «назад» и «вперед», относящихся к определенному сообщению, и структурировать дерево беседы.

    Многопоточность C Thread в Windows

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

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

    Примеры работы инструмента C Thread task

    Многопоточная операционная система может одновременно выполнять несколько фоновых задач, таких как ведение журнала изменений файлов, индексирование данных и управление окнами. Веб-браузеры, поддерживающие многопоточность, могут открывать несколько окон с одновременной работой JavaScript и Flash. Если программа полностью многопоточная, разные процессы не должны влиять друг на друга, если у процессора достаточно мощности для их обработки.

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

    Многозадачность

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

    Историческая ретроспектива

    Ранние операционные системы могли запускать сразу несколько программ, но не полностью поддерживали многозадачность. Одна программа могла потреблять все ресурсы процессора при выполнении определенной операции. Основные задачи операционной системы, такие как копирование файлов, не позволяли пользователю выполнять другие задачи (открытие или закрытие окон, например).

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

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

    Одиночные и многопроцессорные системы

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

    Системы с одним процессором реализуют многопоточность по времени: центральный процессор (CPU) переключается между различными потоками программного обеспечения. В многопроцессорной, а также в многоядерной системе, некоторое количество потоков выполняется в параллельном режиме, причем каждый процессор или ядро ​​выполняют отдельный поток одновременно.

    Виды потоков

    Планировщики процессов большинства современных ОС напрямую поддерживают как временную, так и многопроцессорную потоковую обработку, в то время как ядро ​​операционной системы позволяет разработчикам управлять потоками, предоставляя нужные функции через интерфейс системного вызова. Некоторые потоковые реализации называются потоками ядра, тогда как легкие процессы (LWP) — это тип потока, который имеет одно и то же информационное состояние. Также программные решения могут иметь потоки пространства пользователя, когда они используются с таймерами (Thread timer C), сигналами или другими методами, чтобы прервать их собственное выполнение, выполняя своего рода временную привязку ad hoc.

    Потоки и процессы: отличия

    Потоки отличаются от классических процессов многозадачной ОС следующими характеристиками:

      процессы обычно независимы, тогда как потоки существуют как подмножества процесса;

      процессы несут гораздо больше информации, чем потоки;

      процессы имеют выделенные адресные пространства;

      процессы взаимодействуют только через системные механизмы коммуникации;

      переключение контекста между потоками в процессе происходит оперативнее, чем переключение контекста между процессами.

    Превентивное и совместное планирование

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

    Эволюция технологии

    До начала 2000-х гг. на большинстве настольных компьютеров был только один одноядерный процессор, который не поддерживал аппаратные потоки. В 2002 г. компания Intel реализовала поддержку одновременной многопоточности на процессоре Pentium 4, который носит имя Hyper-Threading. В 2005 г. был представлен двухъядерный процессор и двухъядерный процессор AMD Athlon 64 X2.

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

    Модели

    Перечислим основные модели реализации.

    1: 1 (поток на уровне ядра) — темы, созданные пользователем в ядре, являются простейшей возможной реализацией потоков. OS/2 и Win32 используют этот подход изначально, тогда как в Linux Thread join реализует данный подход через NPTL или более старые LinuxThreads. Этот подход также используется Solaris, NetBSD, FreeBSD, macOS и iOS.

    N: 1 (пользовательский поток) — эта модель предусматривает, что все потоки уровня приложения сопоставляются с одним запланированным объектом уровня ядра. При таком подходе контекстное переключение может быть выполнено очень быстро, и, кроме того, его можно даже реализовать на тех ядрах, которые не поддерживают потоковую обработку. Однако один из основных недостатков заключается в том, что он не выигрывает от аппаратного ускорения на многопоточных процессорах или компьютерах. Например: если один из потоков необходимо выполнить при запросе ввода-вывода, весь процесс блокируется и потоковая передача не может быть использована. В GNU Portable C Thread exception используется как потоковая обработка пользовательского уровня.

    M: N (гибридная реализация) — модель отображает некоторое количество потоков приложений для некоторого N числа ячеек ядра, или «виртуальных процессоров». Это компромисс между потоками уровня ядра («1: 1») и пользователя («N: 1»). Системы потоковой передачи «M: N» более сложны, поскольку требуются изменения как кода ядра, так и кода пользователя. В реализации M: N библиотека потоковой обработки отвечает за планирование потоков в доступных планируемых сущностях. Это делает контекст самым оптимальным, поскольку позволяет избежать вызовов системы. Однако это увеличивает сложность и вероятность инверсии, а также субоптимальное планирование без обширной (и дорогостоящей) координации между планировщиком пользовательской среды и планировщиком ядра.

    Примеры гибридной реализации — активация планировщика, используемая встроенной реализацией библиотеки POSIX NetBSD (для модели M: N, в отличие от модели реализации ядра 1: 1, или модели пользовательского пространства).

    Легкие процессы, используемые более старыми версиями операционной системы Solaris (инструментарий Std Thread C).

    Поддержка языков программирования

    Многие формальные системы поддерживают функциональность потоков. Реализации C и C++ реализуют эту технологию и обеспечивают доступ к собственным API-интерфейсам для операционной системы. Некоторые языки программирования более высокого уровня, такие как языки Java, Python и.NET Framework, выставляют потоки разработчикам при абстрагировании специфических различий в реализации потоков в среде выполнения. Другие языковые расширения также пытаются абстрагировать концепцию параллелизма и потоковой передачи от разработчика. Некоторые языки предназначены для последовательного параллелизма с использованием графических процессоров.

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

    Другие реализации программирования, такие как Tcl, используют расширение Thread sleep C. Это позволяет избегать максимального предела GIL, используя модель, где контент и код должны быть явным образом «разделены» между потоками.

    Языки программирования приложений, ориентированные на события, такие как Verilog, и расширение Thread sleep C, имеют иную модель потоков, которая поддерживает максимальное их число для моделирования оборудования.

    Практическая многопоточность

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