Содержание материала

Semaphore (семафор)

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

Для создания семафора служит функция:

 

function CreateSemaphore(

lpSemaphoreAttributes: PSecurityAttributes; // Адрес структуры

                                             // TSecurityAttributes

lInitialCount,           // Начальное значение счетчика

lMaximumCount: Longint;  // Максимальное значение счетчика

lpName: PChar            // Имя объекта

): THandle; stdcall;

 

Функция возвращает идентификатор созданного семафора, либо 0, если создать объект не удалось.

Параметр lMaximumCount задает максимальное значение счетчика семафора, lInitialCount задает начальное значение счетчика и должен быть в диапазоне от 0 до lMaximumCount. lpName задает имя семафора. Если в системе уже есть семафор с таким именем, то новый не создается, а возвращается идентификатор существующего семафора. В случае если семафор используется внутри одного процесса, можно создать его без имени, передав в качестве lpName значение NIL. Имя семафора не должно совпадать с именем уже существующего объекта типов event, mutex, waitable timer, job, или file-mapping.

Идентификатор ранее созданного семафора может быть, также, получен функцией:

 

function OpenSemaphore(

dwDesiredAccess: DWORD;  // Задает права доступа к объекту

bInheritHandle: BOOL;    // Задает, может ли объект наследоваться

                          // дочерними процессами

lpName: PChar            // Имя объекта

): THandle; stdcall;

 

Параметр dwDesiredAccess может принимать одно из следующих значений:

SEMAPHORE_ALL_ACCESS        Поток получает все права на семафор        

SEMAPHORE_MODIFY_STATE        Поток может увеличивать счетчик семафора функцией ReleaseSemaphore        

SYNCHRONIZE        Только Windows NT поток может использовать семафор в функциях ожидания        

Для увеличения счетчика семафора используется функция:

 

function ReleaseSemaphore(

hSemaphore: THandle;      // Идентификатор семафора

lReleaseCount: Longint;   // Счетчик будет увеличен на эту величину

lpPreviousCount: Pointer  // Адрес 32-битной переменной,

                           // принимающей предыдущее значение

                           // счетчика

): BOOL; stdcall;

 

Если значение счетчика после выполнения функции превысит заданный для него функцией CreateSemaphore максимум, то ReleaseSemaphore возвращает FALSE и значение семафора не изменяется. В качестве параметра lpPreviousCount можно передать NIL, если это значение нам не нужно.

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

Code:

unit LimitedThread;

 

interface

 

uses Classes;

 

type

TLimitedThread = class(TThread)

   procedure Execute; override;

end;

 

implementation

 

uses Windows;

 

const

MAX_THREAD_COUNT = 10;

 

var

Semaphore: THandle;

 

procedure TLimitedThread.Execute;

begin

// Уменьшаем счетчик семафора. Если к этому моменту уже запущено

// MAX_THREAD_COUNT потоков – счетчик равен 0 и семафор в

// несигнальном состоянии. Поток будет заморожен до завершения

// одного из запущенных ранее.

WaitForSingleObject(Semaphore, INFINITE);

 

// Здесь располагается код, отвечающий за функциональность потока,

// например загрузка файла

...

 

// Поток завершил работу, увеличиваем счетчик семафора и позволяем

// начать обработку другим потокам.

ReleaseSemaphore(Semaphore, 1, NIL);

end;

 

initialization

// Создаем семафор при старте программы

Semaphore := CreateSemaphore(NIL, MAX_THREAD_COUNT,

   MAX_THREAD_COUNT, NIL);

 

finalization

// Уничтожаем семафор по завершении программы

CloseHandle(Semaphore);

end;

 

 

Добавить комментарий

Не использовать не нормативную лексику.

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

ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!


Защитный код
Обновить