Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка к лабораторным работам (рус).doc
Скачиваний:
4
Добавлен:
15.11.2018
Размер:
353.79 Кб
Скачать

2.3.3. Семафоры

Обычно, семафором пользуются для учета ресурсов. Как и все объекты ядра, они содержат счетчик числа пользователей, но кроме этого, поддерживают два значения: максимальное число ресурсов и счетчик текущего числа ресурсов.

Объект семафор создается вызовом функции:

HANDLE CreateSemaphore(

LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,

LONG lInitialCount,

LONG lMaximumCount,

LPCTSTR lpName

);

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

Любой процесс может получить свой описатель существующего семафора:

HANDLE OpenSemaphore(

DWORD dwDesiredAccess, // access

BOOL bInheritHandle, // inheritance option

LPCTSTR lpName // object name

);

Поток получает доступ к ресурсу, вызывая одну из Wait-функций и передавая ей описатель семафора. Wait-функция проверяет у семафора счетчик текущего числа ресурсов: если его значение больше 0 (семафор свободен), уменьшает значение этого счетчика на 1, и вызывающий поток становится планируемым. Если же счетчик текущего числа ресурсов равен 0 (семафор занят), система переводит вызывающий поток в состояние ожидания. Когда другой поток увеличит значение этого счетчика, система "вспоминает" о ждущем потоке и начинает снова выделять ему время (при этом снова уменьшив значение счетчика на 1). Последнее действие совершается путем вызова функции

BOOL ReleaseSemaphore(

HANDLE hSemaphore,

LONG lReleaseCount,

LPLONG lpPreviousCount

);

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

Программа завершает работу с семафором вызовом функции

BOOL CloseHandle( HANDLE hObject );

2.3.4.События

Альтернативным и самым простым вариантом синхронизации является использование событий. Объект событие может быть либо свободным (signaled) или установленным (set), либо занятым (non-signaled) или сброшенным (reset). Вы можете создать объект "событие" с помощью функции:

hEvent = CreateEvent(&sa, fManual, fInitial, pszName);

Параметр fInitial устанавливается в TRUE, если вы хотите, чтобы объект Событие был изначально свободным, или в FALSE, чтобы он был занятым.

Параметр pszName определяет имя события. По этому имени разные процессы могут использовать одно событие.

Для того, чтобы сделать свободным существующий объект Событие, надо вызвать функцию:

SetEvent(hEvent);

Чтобы сделать объект Событие занятым, вызывается функция:

ResetEvent(hEvent);

Для синхронизации используются Wait – функции, например:

WaitForSingleObject(hEvent, dwTimeOut);

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

Если параметр fManual имеет значение FALSE при вызове функции CreateEvent, то объект Событие автоматически становится занятым, когда осуществляется возврат из функции WaitForSingleObject. Эта особенность позволяет избежать использования функции ResetEvent.

Уничтожается событие все той же функцией CloseHandle.