Windows для профессионалов


Создание инверсных семафоров и типов данных, безопасных в многопоточной среде


Как-то ряз я писал одну программу, и мне понадобился объект ядра, который вел бы себя прямо противоположно тому, как ведет себя семафор. Мне нужно было, чтобы он переходил в свободное состояние, когда его счетчик текущего числа ресурсов обнуляется, и оставался в занятом состоянии, пока значение этого счетчика больше 0.

Я мог бы придумать много применений такому объекту. Например, потокдолжсн пробудиться после того, как определенная операция будет выполнена 100 раз. Чтобы осуществить это, нужен объект ядра, счетчик которого можно было бы инициализировать этим значением. Пока он больше 0, объект остается в занятом состоянии. По окончании каждой операции Вы уменьшаете счетчик в объекте ядра на 1. Как только счетчик обнуляется, объект переходит в свободное состояние, сообщая другому потоку, что тот может пробудиться и чем-то заняться. Это типичная задача, и я не понимаю, почему в Windows нет подходящего синхронизирующего объекта.

В сущности, Microsoft могла бы легко решить эту задачу, предусмотрев в семафоре возможность присвоения отрицательных значений его счетчику текущего числа ресурсов. Тогда Вы инициализировали бы счетчик семафора значением -99 и по окончании каждой операции вызывали бы ReleaseSemaphore. Как только его счетчик достиг бы значения 1, объект перешел бы в свободное состояние. После этого мог бы пробудиться другой Ваш поток и выполнить свою работу. Увы, Microsoft запрещает присвоение счетчику семафора отрицательных значений, и вряд ли здесь что-то переменится к обозримом будущем.

В этом разделе я познакомлю Вас со своим набором С++-классов, которые действуют как инверсный семафор и делают уйму всяких других вещей. Исходный код этих классов находится в файле Interlocked.h (см листинг на рис. 10-2).

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


Начало  Назад  Вперед