Создание эффективных WIN32-приложений с учетом специфики 64-разрядной версии Windows


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


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

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

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

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

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

Когда я впервые взялся за решение этой проблемы, я понимал, что главное в нем — обеспечить безопасность манипуляций над переменной в многопоточной среде. Я хотел найти элегантное решение, которое позволило бы легко писать код, ссылаю щийся на эту переменную. Очевидно, что самый простой способ обезопасить какой то ресурс от повреждения в многопоточной среде, — защитить его с помощью кри тической секции. В С++ это можно сделать бсз особого труда. Достаточно создать C++ класс, который содержит защищаемую переменную и структуру CRITICAL_SECTION. В конструкторе Вы вызываете lnitializeCriticalSection, а в деструкторе — DeleteCritical Section. Затем для любой переменной-члена Вы вызываете EnterCriticalSection, что-то делаете с этой переменной и вызываете LeaveCriticalSection. Если Вы именно так реа лизуете С++-класс, то писать безопасный код, обращающийся к какой-либо структу ре данных, будет несложно. Этот принцип положен мной в основу всех С++-классов, о которых я буду рассказывать в данном разделе. (Конечно, вместо критических сек ций я мог бы использовать оптекс, рассмотренный в предыдущем разделе.)




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



Книжный магазин