Семафор - это примитив синхронизации потоков, который позволяет войти в заданный участок кода не более чем n потокам (это определение дал выдающийся ученый  Эдсгер Дейкстра).

Обычно семафор нужен для того, чтобы ограничить доступ к некоторому ресурсу, заданным количеством потоков приложения (ресурсом может быть например внешнее устройство, или некий сетевой ресурс).

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

Например, за каждым потоком может скрываться пользователь, который ожидает доступа к ресурсу. Если использовать стандартный класс Semaphore, то доступ к освобождающемуся ресурсу будет получать случайный пользователь, не зависимо от того как давно он ожидает.

Для решения этой задачи, мною был написан класс FifoSemaphore, который реализует политику FIFO (английское First In First Out - первым пришел, первым ушел) по отношению к ожидающим потокам - поток который вызвал функцию Wait первым, должен получить доступ к ресурсу первым. При необходимости, его можно легко модифицировать так, чтобы он работал по принципу LIFO (Last In First Out).

Краткое описание класса

Интерфейс класса аналогичен стандартному классу, за исключением одного нюанса - он не наследует стандартный класс WaitHandle, и соответственно не реализует его свойства и методы (которые специфичны для Windows). Как следствие этот класс не получится использовать в вызове WaitAny

Конструкторы
FifoSemaphore()
 Создает объект.

FifoSemaphore(int _InitialCount)
 Создает объект и инициализирует начальное значение счетчика ресурсов - N;

int Release(int _ReleaseCount)
 Выходит из семафора заданное количество раз (освобождает заданное количество ресурсов), возвращает предыдущее значение счетчика ресурсов;

int Release()
 Выходит из семафора 1 раз, возвращает предыдущее значение счетчика ресурсов;

bool Wait(int _MillisecondsTimeout)
 Входит в семафор. Ожидает освобождения ресурса заданное время в миллисекундах. Если ресурс не был освобожден в указанный период времение, возвращает значение false, иначе - true.

void Close()
 Закрывает семафор и освобождает ресурсы. После этого вызова использовать семафор более не допустимо.

P.S.

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

Загрузить проект с реализацией и тестом: FifoSemaphore.zip (7,85 kb)


Комментарии

Morfant Russia

28 ноября 2009 г. 23:14

Morfant

Не учтена возможность "утечки семафора". Тоесть : "Предположим, например, что у семафора максимальное значение счетчика равно двум, и два потока, A и B входят в семафор. Если ошибка программирования в потоке B заставляет его вызывать метод Release дважды, оба вызова оканчиваются успешно. Счетчик на семафоре достиг максимального значения, и если поток A вызовет метод Release, будет выдано исключение SemaphoreFullException." (MSDN). А у тебя количество ресурсов может расти при вызове метода Release.

Morfant Russia

29 ноября 2009 г. 15:04

Morfant

Ошибка есть - не реализованна проверка на "утечку семафора". [msdn.microsoft.com/.../...threading.semaphore.aspx]

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




  Country flag

biuquote
  • Комментарий
  • Предпросмотр
Loading



maqdev.com

сообщения с ограниченным временем жизни