Презентацию к данной лекции Вы можете скачать здесь.
Многопоточность (multi-
К сожалению, до сих пор мышление многих программистов при разработке программ остается чисто последовательным.
Не учитываются широкие возможности
(рис 10.1) Однопоточный и многопоточный процессы.
Как видно из схемы, однопоточный процесс использует, как обычно, код, данные в основной памяти и файлы, с которыми он работает. Процесс также использует определенные значения регистров и стек, на котором исполняются его процедуры. Многопоточный процесс организован несколько сложнее. Он имеет несколько параллельных потоков, для каждого из которых ОС создает свой стек и хранит свои собственные значения регистров.
Многопоточность имеет большие преимущества:
Использование мультипроцессорных архитектур. Это особенно важно в настоящее время, в период широкого использования многоядерных гибридных и
Как небезынтересно отметить, один из первых шагов на пути к широкому использованию многопоточности, по-видимому, был сделан в 1970-е годы советскими разработчиками компьютерной аппаратуры и программистами. МВК "Эльбрус-1", разработанный в 1979 году, поддерживал в аппаратуре и операционной системе эффективную концепцию процесса, которая была близка к современному понятию облегченного процесса. В частности, процесс в "Эльбрусе" однозначно характеризовался своим стеком. Иначе говоря, все процессы были облегченными и исполнялись в общем пространстве виртуальной памяти – других процессов в "Эльбрусе" просто не было!
Концепция многопоточности начала складываться, по-видимому, с 1980-х гг. в системе
UNIX и ее диалектах. Наиболее развита многопоточность была в диалекте UNIX фирмы
ATT, на основе которого, как уже отмечалось в общем историческом обзоре, была
разработана система Solaris. Все это отразилось и в стандарте
Далее, в середине 1990-х гг. была выпущена ОС Windows NT, в которую была также включена многопоточность.
Однако в разных операционных системах API для многопоточности существенно отличались. Поэтому многопоточные программы, даже написанные на
По-видимому, именно по причине различий в спецификациях и реализациях многопоточности в различных системах профессор Бьярн Страуструп не включил многопоточность в созданный им язык C++, ставший столь популярным, и его базовый набор библиотек. Программисты на языке C++ были вынуждены по-прежнему использовать многопоточность на уровне системных вызовов и библиотек конкретных операционных систем.
Важный шаг вперед сделали авторы языка Java и Java-технологии, первая версия реализации которых была выпущена в 1995 г. Именно в Java впервые многопоточность была реализована на уровне конструкций языка и базовых библиотек. В частности, в Java введен класс Thread,представляющий поток, и операции над ним в виде специальных методов и конструкций языка.
Платформа .NET, появившаяся в 2000 г., предложила свой механизм многопоточности, который фактически является развитием идей Java.
Различие подходов к многопоточности в разных ОС и на разных платформах разработки программ сохраняется и до настоящего времени, что приходится постоянно учитывать разработчикам. Для прикладных программ мы рекомендуем реализовывать многопоточность на платформе Java или .NET, что наиболее удобно и позволяет использовать высокоуровневые понятия и конструкции. Однако в нашем курсе, посвященном операционным системам, мы, естественно, больше внимания уделяем системным вопросам многопоточности и ее реализации в операционных системах.
Модели многопоточности.Реализация многопоточности в ОС, как и многих других возможностей, имеет несколько уровней абстракции. Самый высокий из них – пользовательский уровень. С точки зрения пользователя и его программ,
Низкоуровневые потоки, в которые отображаются пользовательские потоки, называются потоками ядра (kernel threads).Они поддержаны и используются на уровне ядра операционной системы. Как и подходы к пользовательским потокам, подходы к архитектуре и реализации системных потоков и к отображению пользовательских потоков в системные в разных ОС различны. Например, собственные модели потоков ядра со своей спецификой реализованы в следующих ОС:
Существуют различные модели многопоточности – способы отображения пользовательских потоков в потоки ядра. Теоретически возможны (и на практике реализованы) следующие модели многопоточности:
- Модель много / один (many-to-one) – отображение нескольких пользовательских потоков в один и тот же поток ядра. Используется в операционных системах, не поддерживающих множественные системные потоки (например, с целью экономии памяти). Данная модель изображена на рис 10.2.
(рис 10.2) Схема модели многопоточности "много / один".
- Модель один / один (one-to-one) – взаимно-однозначное отображение каждого пользовательского потока
в определенный поток ядра. Примеры ОС, использующих данную модель, -
(рис 10.3) Схема модели многопоточности "один / один".
- Модель много / много (many-to-many) – модель, допускающая отображение нескольких пользовательских потоков в несколько системных потоков. Такая модель позволяет ОС создавать большое число системных потоков. Характерным примером ОС, использующей подобную модель, является ОС Solaris, а также Windows NT / 2000 / XP / 2003 / 2008 / 7 с пакетом .
(рис 10.4) Схема модели многопоточности "много / много".
Многопоточность – весьма сложная, еще не полностью изученная и, тем более, не полностью формализованная область, в которой имеется много интересных проблем. Рассмотрим некоторые из них.
Семантика системных вызовов fork() и exec().Как уже отмечалось, в классической ОС UNIX
Прекращение потоков. Важной проблемой является проблема прекращения потоков: например, если родительский поток прекращается, то должен ли при этом прекращаться дочерний поток? Если прекращается стандартный процесс, создавший несколько потоков, то должны ли прекращаться все его потоки? Ответы на эти вопросы в разных ОС неоднозначны.
Обработка сигналов. Сигналы в UNIX – низкоуровневый механизм обработки ошибочных ситуаций. Примеры сигналов: SIGSEGV - нарушение
Группы потоков. В сложных задачах, например, задачах моделирования, при большом числе разнородных потоков, возникает потребность в их структурировании с помощью концепции группы потоков – совокупности потоков, имеющей свое собственное имя, над потоками которой определены групповые операции. Наиболее удачно, с нашей точки зрения, группы потоков реализованы в Java (с помощью класса ThreadGroup ). Следует отметить также
Локальные данные потока (thread-local storage - TLS) – данные, принадлежащие только определенному потоку и используемые только этим потоком. Необходимость в таких данных очевидна, так как многопоточность – весьма важный метод распараллеливания решения большой задачи, при котором каждый
) могут использовать общие ресурсы и реагировать на общие события, необходимы средства их синхронизации. Эти средства подробно рассмотрены позже в данном курсе.
), потоки могут взаимно блокировать друг друга (т.е. может создаться ситуация deadlock ), при их неаккуратном программировании. Меры по борьбе с
В качестве конкретной модели многопоточности рассмотрим потоки
Стандарт
Стандарт
pthread_create(): создание потокаpthread_exit():завершение потока (должна вызываться функцией потока при завершении)pthread_cancel():отмена потокаpthread_join():заблокировать выполнение потока до прекращения другого потока, указанного в вызове функцииpthread_detach():освободить ресурсы занимаемые потоком (если поток выполняется, то pthread_attr_init():инициализировать структуру атрибутов потокаpthread_attr_setdetachstate():указать системе, что после завершения потока она может автоматически освободить ресурсы, занимаемые потокомpthread_attr_destroy():освободить память от структуры атрибутов потока (уничтожить дескриптор).Имеются следующие примитивы синхронизации
- pthread_mutex_init() – создание мьютекса;- pthread_mutex_destroy() – уничтожение - pthread_mutex_lock() – закрытие - pthread_mutex_trylock() – пробное закрытие - pthread_mutex_unlock() – открытие - pthread_cond_init() – создание - pthread_cond_signal() – разблокировка - pthread_cond_wait() – ожидание по Рассмотрим пример использования
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
static void wait_thread(void)
{
time_t start_time = time(NULL);
while (time(NULL) == start_time)
{
// никаких действий, кроме занятия процессора на время до 1 с.
}
}
static void *thread_func(void *vptr_args)
{ int i;
for (i = 0; i < 20; i++) {
fputs(" b\n", stderr);
wait_thread();
}
return NULL;
}
int main(void)
{ int i;
pthread_t thread;
if (pthread_create(thread, NULL, thread_func, NULL) != 0) {
return EXIT_FAILURE;
}
for (i = 0; i < 20; i++) {
puts("a");
wait_thread();
}
if (pthread_join(thread, NULL) != 0) {
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Пример иллюстрирует параллельное выполнение основного потока, выдающего в
В ОС Solaris, как уже было отмечено, используется модель потоков много / много. Кроме того, в системе используется также уже известное нам понятие облегченный процесс (lightweight process) промежуточное между концепцией пользовательского потока и системного потока. Таким образом, в ОС Solaris каждый пользовательский поток отображается в свой облегченный процесс, который, в свою очередь, отображается в поток ядра; последний может исполняться на любом процессоре (или ядре процессора) компьютерной системы. Схема организации потоков в Solaris изображена на рис 10.5.
(рис 10.5) Потоки в Solaris.
На рис 10.6 изображена схема организации процесса в ОС Solaris.
(рис 10.6) Процессы в Solaris.
На схеме видно, что каждый процесс содержит, кроме стандартной информации
Как уже отмечалось, в системе Windows реализована модель многопоточности "один / один". Каждый поток содержит:
В системе Linux потоки называются tasks (задачами),а не threads. Поток создается системным вызовом
Как уже отмечалось, Java – первая платформа для разработки программ, в которой многопоточность поддержана на уровне языка и базовых библиотек. Потоки в Java могут быть созданы следующими способами:
Потоки в Java управляются
Возможные состояния потоков в Java изображены на рис 10.7. Подобно потокам в ОС, поток в Java создается и находится в состоянии новый, затем – выполняемый ; при вызове методов типа wait, sleep и др. поток переходит в состояние ожидания; при завершении метода run поток завершается.
(рис 10.7) Состояния потоков в Java.
Mac C- – пользовательские потоки в системе MacOS.
потоки, специфицированные стандартом
Solaris – пользовательские потоки в ОС Solaris.
– класс, представляющий поток, в языке Java.
Атрибуты потока – совокупность атрибутов pthread_attr_t.
Группа потоков ( – совокупность потоков, имеющей свое
собственное имя, над потоками которой определены групповые операции.
Дескриптор потока – ссылка на POSIX-поток, описываемая типом pthread_t.
Задача (task) – название потока в Linux.
Исключение (exception) – высокоуровневый механизм обработки ошибочных ситуаций в объектно-ориентированных языках и операционных системах.
Локальные данные потока (thread-local storage - TLS) – данные, принадлежащие только определенному потоку и используемые только этим потоком.
Модель многопоточности – способ отображения пользовательских потоков в потоки ядра.
Модель много / много - модель многопоточности,при которой различные пользовательские потоки могут быть отображены в различные потоки ядра.
Модель много / один - модель многопоточности, при которой несколько пользовательских потоков могут быть отображены в один поток ядра.
Модель один / один – модель многопоточности, при которой каждый пользовательский поток отображается в один определенный поток ядра.
Мьютекс (mutex) – аналог семафоров, обеспечивающий взаимное исключение, используемый в операционных системах.
Облегченный процесс (lightweight process) – процесс, работающий в общем пространстве виртуальной памяти с процессом-родителем.
Поток (thread) – запускаемый из какого-либо процесса более эффективный вариант
Поток пользовательского уровня (user thread) - высокоуровневый поток, операции над которым включены в интерфейс пользователя ОС.
Поток ядра (kernel thread) - низкоуровневый системный поток, поддержанный и использующийся на уровне ядра операционной системы; используется для реализации потоков пользовательского уровня.
Пул потоков (ThreadPool) –
Сигналы (в UNIX) – низкоуровневый механизм обработки ошибочных ситуаций.
"Тяжеловесный" (heavyweight) процесс – название классического процесса, работающего в собственном адресном пространстве, в противоположность облегченному процессу.
Условная переменная (conditional variable) - синхронизирующий объект,
используемый в операционных системах, с операциями и .
Многопоточность (multi-
Впервые понятие процесса, близкое современной концепции потока, было реализовано в системе "Эльбрус" в конце 1970-х гг. Многопоточность появилась в UNIX, затем – в Solaris и Windows NT. В различных ОС архитектуры библиотек поддержки многопоточности различаются. В Java-технологии, а вслед за ней – в .NET, впервые многопоточность была реализована на уровне языка и базовых библиотек.
Архитектура потоков – многоуровневая: потоки пользовательского уровня реализуются с помощью системных потоков (потоков ядра). Существуют различные модели многопоточности (способы отображения пользовательских потоков в системные) – один-один, один-много, много-один.
Многопоточность ставит ряд интересных проблем: семантика системных вызовов
Потоки в ОС Solaris отличаются тем, что явно присутствует понятие облегченного процесса, наряду с понятиями пользовательского и системного потоков. Каждый традиционный процесс хранит список созданных в нем облегченных процессов. Используется модель многопоточности "много-много".
В Windows 2000 используется модель многопоточности "один-один". Каждый поток содержит свой номер, набор регистров, отдельные стеки для пользовательских и системных процедур,
В Linux потоки называются задачами (tasks) и создаются системным вызовом
Потоки в Java поддержаны на уровне языка и базовых библиотек. Представляются объектами класса
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.