Лабораторный практикум по курсу "Операционные системы"
Идентификатор потока определяет, какой поток захватил мьютекс, а счетчик рекурсий —
сколько раз. У мьютексов много применений, и это наиболее часто используемые объекты
ядра. Как правило, с их помощью защищают блок памяти, к которому обращается множество
потоков. Если бы потоки одновременно использовали какой-то блок памяти, данные в нем
были бы повреждены
. Мьютексы гарантируют, что любой поток получает монопольный
доступ к блоку памяти, и тем самым обеспечивают целостность данных.
Для использования объекта-мьютекса один из процессов должен сначала создать его
вызовом CreateMutex:
HANDLE CreateMutex( PSECURITY_ATTRIBUTES psa,
BOOL fIniLialOwner,
PCTSTR pszName);
Разумеется, любой процесс может получить свой («процессо-зависимый») описатель
существующего объекта «мьютекс», вызвав OpenMutex:
HANDLE OpenMutex( DWORD fdwAccess,
B00L bInheritHandle,
PCTSTR pszName);
Параметр fInitialOwner определяет начальное состояние мъютекса. Если в нем передается
FALSE (что обычно и бывает), объект-мьютекс не принадлежит ни одному из потоков и
поэтому находится в свободном состоянии. При этом его идентификатор потока и счетчик
рекурсии равны 0. Если же в нем передается TRUE, идентификатор потока, принадлежащий
мьютексу, приравнивается идентификатору вызывающего потока, а
счетчик рекурсии
получает значение 1. Поскольку теперь идентификатор потока отличен от 0, мьютекс
изначально находится в занятом состоянии.
Поток получает доступ к разделяемому ресурсу, вызывая одну из Wait-функций и передавая
ей описатель мьютекса, который охраняет этот ресурс. Wait-функция проверяет у мьютекса
идентификатор потока, если его значение не равно 0, мьютекс свободен, в ином случае
оно
принимает значение идентификатора вызывающего потока, и этот поток остается
планируемым.
Если Wait-функция определяет, что у мьютекса идентификатор потока не равен 0 (мьютекс
занят), вызывающий поток переходит в состояние ожидания. Система запоминает это и,
когда идентификатор обнуляется, записывает в него идентификатор ждущего потока, а
счетчику рекурсии присваивает значение 1, после чего ждущий
поток вновь становится
планируемым. Все проверки и изменения состояния объекта-мьютекса выполняются на
уровне атомарного доступа.
Когда ожидание мьютекса потоком успешно завершается, последний получает монопольный
доступ к защищенному ресурсу. Все остальные потоки, пытающиеся обратиться к этому
ресурсу, переходят в состояние ожидания Когда поток, занимающий ресурс, заканчивает с
ним работать, он должен
освободить мьютекс вызовом функции ReleaseMutex
BOOL ReleaseMutex(HANDLE hMutex);
Эта функция уменьшает счетчик рекурсии в объекте-мьютексе на 1. Если данный объект
передавался во владение потоку неоднократно, поток обязан вызвать ReleaseMutex столько
раз, сколько необходимо для обнуления счетчика рекурсии. Как только счетчик станет равен
0, переменная, хранящая идентификатор потока, тоже обнулится, и объект-мьютекс
освободится. После этого система проверит, ожидают ли освобождения
мьютекса какие-
Учебно-исследовательская лаборатория «Информационные технологии» 143