Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

лекции СПО

.pdf
Скачиваний:
30
Добавлен:
03.06.2015
Размер:
2.4 Mб
Скачать

Рис. 4.19. Ре лиз ция вз имно о исключения с использов нием системных функций вход в критическую секцию и выход из нее

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

локирующих переменных. Действительно, в т кой ситу ции н кл дные р сходы ОС по ре лиз ции функции вход в критическую секцию и выход из нее мо ут превысить полученную экономию.

7.5 Семафоры

 

 

 

 

 

 

 

 

 

О о щением

локирующих

переменных

являются т к

н зыв емые

сем форы Дийкстры. Вместо двоичных переменных

Дийкстр

(Dijkstra)

предложил

использов ть переменные,

которые

 

мо ут

приним ть

целые

неотриц тельные

 

зн чения.

Т кие

переменные,

используемые

для

синхрониз ции вычислительных процессов, получили н зв ние сем форов.

Для

р оты

с сем фор ми

вводятся дв

 

примитив , тр диционно

о озн ч емых Р и V. Пусть переменн я S предст вляет со ой сем фор. То д

действия V(S) и P(S) определяются следующим о р зом.

 

 

 

 

V(S):

переменн я

S

увеличив ется

н

1

единым

действием.

Вы орк , н р щив ние и з помин ние не

 

мо ут

ыть прерв ны. К

переменной S нет доступ

дру им поток м во время выполнения этой

опер ции;

 

 

 

 

 

 

 

 

 

 

 

 

P(S):

уменьшение

S

н

1,

если это

возможно. Если

S=0 и

невозможно уменьшить S, ост в ясь в о л сти целых неотриц тельных зн чений, то в этом случ е поток, вызыв ющий опер цию Р, ждет, пок это уменьшение ст нет возможным. Успешн я проверк и уменьшение т кже являются неделимой опер цией;

Ник кие прерыв ния во время выполнения примитивов V и Р

недопустимы.

В ч стном случ е, ко д сем фор S может приним ть только зн чения 0

и 1, он превр щ ется в локирующую переменную, которую по этой причине

ч сто н зыв ют

двоичным

сем фором.

Опер ция

Р з ключ ет

в се е

потенци льную

возможность

переход

поток ,

который

ее выполняет, в

состояние ожид ния, в то время

к к

опер ция

V

может при некоторых

о стоятельств х

ктивизиров ть дру ой поток, приост новленный опер цией Р.

Р ссмотрим использов ние

сем форов

н

 

кл ссическом

примере

вз имодействия

двух выполняющихся

в

режиме

мультипро р ммиров ния

потоков, один из которых пишет д нные в

уферный пул,

дру ой считыв ет

их из уферно о пул . Пусть уферный пул состоит из N уферов, к ждый из

которых может содерж ть одну з пись. В о щем случ е поток-пис тель и

поток-чит тель мо ут иметь р зличные скорости и о р щ ться к уферному

пулу с переменой интенсивностью. В один период скорость з писи может превыш ть скорость чтения, в дру ой — н о орот. Для пр вильной совместной

р оты

поток-пис тель

должен приост н влив ться,

ко д

все

 

уферы

ок зыв ются з нятыми, и

ктивизиров ться при осво ождении хотя

ы одно о

уфер .

Н против,

поток-чит тель

должен приост н влив ться, ко д

все

уферы пусты, и ктивизиров ться при появлении хотя

ы одной з писи.

 

 

Введем дв

сем фор : е —

число

пустых

уферов,

и f

число

з полненных

уферов, причем в исходном состоянии е =N, a f =0. То д

р

от

потоков с о щим

уферным пулом может

ыть опис н

следующим о р зом

(рис. 4.20).

 

 

 

 

 

 

 

 

 

 

 

Поток-пис тель прежде все о выполняет опер цию Р(е), с помощью

которой он проверяет, имеются ли в

уферном пуле нез полненные

уферы. В

соответствии с сем нтикой опер ции Р, если сем фор е р вен 0

(то

есть

сво одных

уферов в д нный момент нет), то поток-пис тель переходит в

состояние ожид ния. Если же зн чением е является положительное число, то он

уменьш ет

число сво одных

уферов,

з писыв ет

д нные

в очередной

сво одный

уфер и после это о н р щив ет число з нятых уферов опер цией

V(f). Поток-чит тель действует

н ло ичным о р зом, с той р зницей, что он

н чин ет р

оту с проверки н личия з полненных

уферов,

после чтения

д нных н р щив ет количество сво одных

уферов.

 

 

Рис. 4.20. спользов ние сем форов для синхрониз ции потоков В д нном случ е предпочтительнее использов ть сем форы вместо

локирующих переменных. Действительно, критическим ресурсом здесь

является

уферный

пул, который

может ыть предст влен

к к н

ор

идентичных ресурсов — отдельных

уферов,

зн чит, с

уферным пулом

мо ут р

от ть ср зу несколько потоков, и именно столько, сколько уферов в

нем

содержится.

спользов ние

двоичной

переменной

не

позволяет

ор

низов ть

доступ

к

критическому ресурсу

олее чем одному потоку.

Сем фор

же

реш ет

з д чу синхрониз ции

олее и ко,

допуск я

к

р зделяемому

пулу ресурсов з д нное количество потоков. Т к, в н шем

примере с уферным пулом мо ут р

от ть м ксимум N потоков, ч сть из

которых может

ыть «пис телями»,

ч сть — «чит телями».

 

Т ким

о р зом,

сем форы

позволяют

эффективно реш ть

з д чу

синхрониз ции

Доступ

к ресурсным

пул м,

т ким, н пример, к к

н ор

идентичных в функцион льном н зн чении внешних устройств (модемов,

принтеров, портов), или н ор о л стей п мяти один ковой величины, или

информ ционных структур. Во всех этих и подо ных им случ ях с помощью

сем форов можно ор низов ть

доступ к р зделяемым ресурс м ср зу

нескольких потоков.

 

Сем фор может использов ться и в к честве локирующей переменной.

В р ссмотренном выше примере,

для то о что ы исключить коллизии при

р

оте с р зделяемой о л стью п мяти,

удем счит ть,

что з пись в уфер и

считыв ние

из

уфер

являются критическими

секциями. Вз имное

исключение

удем о еспечив ть с помощью двоично о сем фор b (рис. 4.21).

О

поток

после проверки доступности

уферов должны выполнить проверку

доступности критической секции.

Рис. 4.21. спользов ние двоично о сем фор

7.6 Тупики

Приведенный выше пример позволяет т кже проиллюстриров ть еще одну про лему синхрониз ции — вз имные локировки, н зыв емые т кже

дедлок ми (deadlocks), клинч ми (clinch), или тупик ми.

Вз имн я локировк ( н л. deadlock) или тупик — ситу ция в

мно оз д чной среде, при которой несколько процессов н ходятся в состоянии

есконечно о ожид ния ресурсов, з хв ченных с мими этими процесс ми.

Пок жем, что если перест вить мест ми опер ции Р(е) и Р(b) в потоке-

пис теле,

то при некотором стечении

о стоятельств эти дв поток мо ут

вз имно

локиров ть дру дру , т к,

пусть поток-пис тель н чин ет свою

р оту с проверки доступности критической секции — опер ции Р(b), и пусть

он первым войдет в критическую секцию. Выполняя опер цию Р(е), он может

о н ружить отсутствие сво одных уферов и перейти в состояние ожид ния.

К к уже ыло пок з но, из это о состояния е о может вывести только поток-

чит тель, который возьмет очередную з пись из уфер . Но поток-чит тель не

сможет это о сдел ть, т к к к для это о ему потре уется войти в критическую

секцию, вход в которую з

локиров н потоком-пис телем. Т ким о р зом, ни

один из этих потоков не может з вершить н ч тую р

оту

и

возникнет

тупиков я ситу ция, котор я не может р зрешиться

ез внешне о воздействия.

 

Р ссмотрим

еще

 

один

пример

тупик .

Пусть

двум

поток м,

прин длеж щим

р зным

процесс м

и

выполняющимся

в

 

режиме

мультипро р ммиров ния,

для

выполнения их р

оты

нужно

дв

 

ресурс ,

н пример

принтер

и

последов тельный

порт.

Т к я

ситу ция

может

возникнуть, н пример, во время р

оты приложения, з д чей которо о является

р спеч тк

информ ции, поступ ющей по модемной связи.

 

 

 

 

 

 

Н

рис. 4.22,

пок з ны фр

менты соответствующих про р мм. Поток

А

з пр шив ет

сн ч л

 

принтер;

 

з тем

порт,

поток В

з пр шив ет

устройств

в

о р тном

порядке.

Предположим,

что после то о, к к ОС

н зн чил

принтер

потоку А

и

уст новил

связ нную с этим ресурсом

локирующую переменную, поток А

ыл прерв н. Упр вление получил поток

В, который сн ч л

выполнил з прос н

получение СОМ-

порт ,

з тем при

выполнении следующей ком нды

ыл з локиров н, т к к к принтер ок з лся

уже з нятым потоком А. Упр вление снов

получил поток А, который в

соответствии

со

своей

про р ммой

сдел л

попытку

з нять

порт

и

ыл

з

локиров н,

поскольку порт уже выделен потоку В.

В т ком положении

потоки А и В мо ут н ходиться сколь у одно дол о.

 

 

 

 

 

 

 

 

В з висимости от соотношения скоростей

потоков

они

мо ут

ли о

вз имно

локиров ть дру

дру

(рис. 4.22,

), ли о о р зовыв ть очереди к

р зделяемым

ресурс м

 

(рис. 4.22, в),

ли о

совершенно

нез висимо

использов ть р зделяемые ресурсы (рис. 4.22,

).

 

 

 

 

 

 

 

Рис. 4.22. Возникновение взаимных блокировок при выполнении программы

ПРИМЕЧАНИЕ

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

В рассмотренных примерах тупик был образован двумя потоками, но взаимно блокировать друг друга может и большее число потоков. На рис. 2.23 показано такое распределение ресурсов Ri между несколькими потоками Tj, которое привело к возникновению взаимных блокировок. Стрелки

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

для выполнения работы необходимы ресурсы R1 и R2, из которых выделен только один — R1, а

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

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

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

Рис. 4.23. Взаимная блокировка нескольких потоков

Тупики могут быть предотвращены на стадии написания программ, то есть программы должны быть написаны таким образом, чтобы тупик не мог возникнуть при любом соотношении взаимных скоростей потоков. Так, если бы в примере, показанном на рис. 4.22, поток А и поток В запрашивали ресурсы в одинаковой последовательности, то тупик был бы>в принципе невозможен. Другой, более гибкий подход к предотвращению тупиков заключается в том, что ОС каждый раз при запуске задач анализирует их потребности в ресурсах и определяет, может ли в данной мультипрограммной смеси возникнуть тупик. Если да, то запуск новой задачи временно откладывается. ОС может также

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

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

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

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

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

7.7 Синхронизирующие объекты ОС

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

Примерами таких синхронизирующих объектов ОС являются системные семафоры, мьютексы,

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

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

Кроме того, для синхронизации могут быть использованы такие «обычные» объекты ОС, как файлы,

процессы и потоки. Все эти объекты могут находиться в двух состояниях: сигнальном и несигнальном

— свободном. Для Каждого объекта смысл, вкладываемый в понятие «сигнальное состояние»,

зависит от типа объекта. Так, например, поток переходит в сигнальное состояние тогда, когда он завершается. Процесс переходит в сигнальное состояние тогда, когда завершаются все его потоки.

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

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

помощью которого поток может перевести объект синхронизации в сигнальное состояние, назовем

Set(X).

Поток, выполнивший системный вызов Wait(X), переводится операционной системой в состояние ожидания до тех пор, пока объект X не перейдет в сигнальное состояние. Примерами системных вызовов типа Wait() и Set() являются вызовы WaitForSingleObject() и SetEvent() в Windows NT,

DosSenWait() и OosSemSet() в OS/2, sleep() и wakeup() в UNIX.

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

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

либо один из них.

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

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

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

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

основной поток создает вспомогательные серверные потоки.