Мьютексы

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

Мьютекс — это совместно используемая переменная, которая может находиться в одном из двух состояний: заблокированном или незаблокированном. Следовательно, для их представления нужен только один бит, но на практике зачастую используется целое число, при этом нуль означает незаблокированное, а все остальные значения — заблокированное состояние. Для работы с мьютексами используются две процедуры. Когда потоку (или процессу) необходим доступ к критической области, он вызывает процедуру тМвх_1оск. Если мьютекс находится в незаблокированном состоянии (означающем доступность входа в критическую область), вызов проходит удачно и вызывающий поток может свободно войти в критическую область.

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

Благодаря исключительной простоте мьютексов они легко могут быть реализованы в пользовательском пространстве при условии доступности команды ТБЬ или ХОНС. В листинге 2.7 показан код процедур тШвх_1оск и тМвх_ип1оск, предназначенных для использования в совокупности потоков, работающих в пользовательском пространстве. Решение, в котором используется команда ХОНС, по сути, ничем не отличается.


Листинг 2.7. Реализация mutexjock и mutex_unlock


| сохранение в мьютексе значения 0 | возврат управления вызывающей программе

Код процедуры mutex_lock похож на код enter_region в листинге 2.2, но с одной существенной разницей. Когда процедуре enter_region не удается войти в критическую область, она продолжает повторное тестирование значения переменной lock (выполняет активное ожидание). По истечении определенного времени планировщик возобновляет работу какого-нибудь другого процесса. Рано или поздно возобновляется работа процесса, удерживающего блокировку, и он ее освобождает.

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

Вот в этом и заключается разница между enter_region и mutex_lock.

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

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

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

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

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

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

<< | >>
Источник: Э. ТАНЕНБАУМ Х. БОС. СОВРЕМЕННЫЕ ОПЕРАЦИОННЫЕ СИСТЕМ Ы 4-е ИЗДАНИЕ. 2015

Еще по теме Мьютексы:

  1. Л.О. Доліненко, В.О. Доліненко, С.О. Сарновська. Цивільне право України, 2006
  2. ЦИВІЛЬНЕ ПРАВО УКРАЇНИ
  3. ПЕРЕДМОВА
  4. Частина І ПРОГРАМА КУРСУ «ЦИВІЛЬНЕ ПРАВО УКРАЇНИ»
  5. Розділ І. Загальні положення цивільного права
  6. Тема 1. Поняття цивільного права. Предмет та метод, система цивільного права. Функції та принципи цивільного права
  7. Тема 2. Цивільне законодавство України
  8. Тема 3. Поняття, елементи та види цивільних правовідносин
  9. Тема 4. Здійснення цивільних прав і виконання обов’язків
  10. Тема 5. Захист цивільних прав та інтересів
  11. Тема 6. Об’єкти цивільних прав
  12. Тема 7.ФІЗИЧНІ особи як суб’єкти цивільного права
  13. Тема 8. Юридичні особи
  14. Тема 9. Держава як суб’єкт цивільного права. Територіальні громади та Автономна Республіка Крим як суб’єкти цивільного права
  15. Тема 10. Правочини: поняття, види. Умови чинності правочину