К Т П           План занятия                                                              1                                           Страницы  | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | | 7 | | 8 | | 9 |

4. Мьютексы

Для решения проблемы взаимного исключения между параллельными потоками, выполняющимися в контекстах разных процессов, в операционных системах Windows используется объект ядра мьютекс. Слово мьютекс происходит от английского слова mutex, которое в свою очередь является сокращением от выражения mutual exclusion, что на русском языке значит "взаимное исключение". Мьютекс находится в сигнальном состоянии, если он не принадлежит ни одному потоку. В противном случае мьютекс находится в несигнальном состоянии. Одновременно мьютекс может принадлежать только одному потоку.

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

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

HANDLE CreateMutex(
        LPSECURITY_ATTRIBUTES lpMutexAttributes, // атрибуты защиты
        BOOL blnitialOwner, // начальный владелец мьютекса
        LPCTSTR lpName // имя мьютекса
     );

Пока значение параметра lpsecurity_attributes будем устанавливать в null. Это означает, что атрибуты защиты заданы по умолчанию, т. е. дескриптор мьютекса не является наследуемым и доступ к мьютексу открыт для всех пользователей. Теперь перейдем к другим параметрам.

Если значение параметра binitiaiowner равно true, то мьютекс сразу переходит во владение потоку, которым он был создан. В противном случае вновь созданный мьютекс свободен. Поток, создавший мьютекс, имеет все права доступа к этому мьютексу.

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

В случае удачного завершения функция CreateMutex возвращает дескриптор созданного мьютекса. В случае неудачи эта функция возвращает значение null. Если мьютекс с заданным именем уже существует, то функция CreateMutex возвращает дескриптор этого мьютекса, а функция GetLastError, вызванная после функции CreateMutex, вернет значение ERROR_ALREADY_EXISTS.

Мьютекс захватывается потоком посредством любой функции ожидания, а освобождается функцией ReleaseMutex, которая имеет следующий прототип:

BOOL ReleaseMutex (
        HANDLE hMutex // дескриптор мьютекса
     );

В случае успешного завершения функция ReleaseMutex возвращает ненулевое значение, а в случае неудачи — false. Если поток освобождает мьютекс, которым он не владеет, то функция ReleaseMutex возвращает значение false.

Для доступа к существующему мьютексу поток может использовать одну из функций CreateMutex или OpenMutex. Функция CreateMutex используется в тех случаях, когда поток не знает, создан или нет мьютекс с указанным именем другим потоком. В этом случае значение параметра binitialOwner нужно установить в false, т. к. невозможно определить какой из потоков создает мьютекс. Если поток использует для доступа к уже созданному мьютексу функцию CreateMutex, то он получает полный доступ к этому мьютексу.

Для того чтобы получить доступ к уже созданному мьютексу поток может также использовать функцию openMutex, которая имеет следующий прототип:
  HANDLE OpenMutex (
    DWORD dwDesiredAccess, // доступ к мьютексу
    BOOL blnheritHandle // свойство наследования
    LPCTSTR lpName // имя мьютекса
  );

Параметр dwDesiredAccess этой функции может принимать одно из двух значений:
- MUTEX_ALL_ACCESS — полный доступ;
- SYNCHRONIZE — синхронизация.

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

Параметр blnheritHandle определяет свойство наследования мьютекса. Если значение этого параметра равно true, то дескриптор открываемого мьютекса является наследуемым. В противном случае дескриптор не наследуется.

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

 


Предыдущая        В начало страницы       Следующая
4