Визуальное программирование и MFC

       

Объекты синхронизации и классы MFC


Интерфейс Win32 поддерживает четыре типа объектов синхронизации - все они так или иначе основаны на понятии семафора.

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

Вторым типом объектов синхронизации является исключающий (mutex) семафор. Он предназначен для полного ограничения доступа к ресурсу, чтобы в любой момент времени к ресурсу мог обратиться только один процесс или поток. Фактически, это особая разновидность семафора.

Третьим типом объектов синхронизации является событие, или объект события (event object). Он используется для блокирования доступа к ресурсу до тех пор, пока какой-нибудь другой процесс или поток не заявит о том, что данный ресурс может быть использован. Таким образом, данный объект сигнализирует о выполнении требуемого события.

При помощи объекта синхронизации четвертого типа можно запрещать выполнения определенных участков кода программы несколькими потоками одновременно. Для этого данные участки должны быть объявлены как критический раздел (critical section). Когда в этот раздел входит один поток, другим потокам запрещается делать тоже самое до тех пор, пока первый поток не выйдет из данного раздела.

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

В MFC механизм синхронизации, обеспечиваемый интерфейсом Win32, поддерживается с помощью следующих классов, порожденных от класса CSyncObject:


  • CCriticalSection - реализует критический раздел.


  • CEvent - реализует объект события


  • CMutex - реализует исключающий семафор.


  • CSemaphore - реализует классический семафор.


  • Кроме этих классов в MFC определены также два вспомогательных класса синхронизации: CSingleLock и CMultiLock. Они контролируют доступ к объекту синхронизации и содержат методы, используемы для предоставления и освобождения таких объектов. Класс CSingleLock управляет доступом к одному объекту синхронизации, а класс CMultiLock - к нескольким объектам. Далее будем рассматривать только класс CSingleLock.

    Когда какой-либо объект синхронизации создан, доступ к нему можно контролировать с помощью класса CSingleLock. Для этого необходимо сначала создать объект типа CSingleLock с помощью конструктора:

    CSingleLock( CSyncObject* pObject, BOOL bInitialLock = FALSE );

    Через первый параметр передается указатель на объект синхронизации, например семафор. Значение второго параметра определяет, должен ли конструктор попытаться получить доступ к данному объекту. Если этот параметр не равен нулю, то доступ будет получен, в противном случае попыток получить доступ не будет. Если доступ получен, то поток, создавший объект класса CSingleLock, будет остановлен до освобождения соответствующего объекта синхронизации методом Unlock класса CSingleLock.

    Когда объект типа CSingleLock создан, доступ к объекту, на который указывал параметр pObject, может контролироваться с помощью двух функций: Lock и Unlock класса CSingleLock.

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

    Метод Unlock освобождает объект синхронизации, давая возможность другим потокам использовать ресурс.


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

    При работе с классом CSingleLock общая процедура управления доступом к ресурсу такова:

  • создать объект типа CSyncObj (например, семафор), который будет использоваться для управления доступом к ресурсу;


  • с помощью созданного объекта синхронизации создать объект типа CSingleLock;


  • для получения доступа к ресурсу вызвать метод Lock;


  • выполнить обращение к ресурсу;


  • вызвать метод Unlock, чтобы освободить ресурс.


  • Далее описывается, как создавать и использовать семафоры и объекты событий. Разобравшись с этими понятиями, можно достаточно просто изучить и использовать два других типа объектов снхронизации: критические секции и мьютексы.


    Содержание раздела