Изучение средств синхронизации процессов и потоков в ОС Windows: Методические рекомендации по выполнению лабораторной работы, страница 3

В Приложении 3  приведен пример программы, показывающий  создание и использование мьютекса [2]. Программа создает мьютекс и отображает окно сообщения, информирующее, что она владеет мютексом. Если запустить программу один раз, а затем - вторую копию программы, то вторая копия не сможет стать владельцем мьютекса, пока первая программа не закончит свою работу, т.е. пока пользователь не закроет диалоговое окно. При запуске нескольких копий программы только одна из них может вывести на экран окно сообщения.

2.4.Семафоры  (semaphores)

Семафоры, как и мьютексы, служат для ограничения одновременного доступа к ресурсу нескольких потоков. При создании семафора необходимо указать начальное значение счетчика семафора. Счетчик определяет максимальное количество потоков, которые одновременно  могут работать с ресурсом. Если программа обращается к семафору, значение счетчика уменьшается на единицу. Когда значение счетчика равно нулю, семафор становится недоступным и блокируется доступ к ресурсу («семафор закрыт»).

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

Обычно используются семафоры, которые принимают два значения – 0 или 1. Задача перед тем, как использовать ресурс, захватывает семафор. Остальные потоки , желающие использовать тот же ресурс, должны ожидать освобождения семафора.

Системные вызовы семафора аналогичны соответствующим функциям уже рассмотренных выше объектов синхронизации.

Для создания нового семафора или открытия существующего служит функция CreateSemaphore().   Синтаксис этой функции:

HANDLE CreateSemaphore(

LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,  // указатель на структуру   //безопасности

    LONG lInitialCount,          // начальное значение счетчика семафора

    LONG lMaximumCount,    // максимальное значение счетчика

    LPCTSTR lpName             // указатель на строку – имя семафора 

   ).

Функция   HANDLE     OpenSemaphore(

      DWORD   dwDesiredAccess,      // флаг доступа

      BOOL    bInheritHandle,            // флаг наследования

      LPCTSTR   lpName                   // указатель на имя семафора

 )  открывает существующий семафор и возвращает дескриптор (хэндл) семафора.

Функция     BOOL ReleaseSemaphore(

    HANDLE    hSemaphore,             // хэндл семафора 

    LONG       lReleaseCount,    // значение в счетчике семафора при его освобождении 

    LPLONG   lpPreviousCount        // адрес предыдущего значения счетчика

) освобождает семафор.  Когда поток заканчивает использование ресурса, он вызывает эту функцию и увеличивает значение семафора на единицу.

В Приложении 4  приведен пример программы [2], иллюстрирующей работу семафора. Программа показывает использование семафоров для синхронизации потоков. Основной поток создает семафор  и устанавливает его в состояние нуль ("семафор закрыт").  Этот поток создает файл, записывает в него строку, закрывает  файл и до освобождения семафора запускает новый поток, который должен открыть файл, прочитать из него строку символов и вывести  её на экран. После запуска нового потока и перевода его в состояние  ожидания  освобождения семафора основной поток переводит его в сигнальное состояние,

3.  ЗАДАНИЕ   И   ПОРЯДОК   ВЫПОЛНЕНИЯ     РАБОТЫ

1.  Изучите назначение и синтаксис функций API  Windows для работы с событиями, как объектами синхронизации. Используйте для этого раздел 2 описания лабораторной работы, справочную систему Windows API и рекомендуемую литературу.

2.  Ознакомьтесь с программой, приведенной в Приложении 1. Запустите программу, пронаблюдайте её работу и особенности использования событий.

3.  Изучите работу программы из Приложения 2.

4.  Изучите назначение и особенности использования мьютексов, а также функции API Windows для работы с мьютексами.

5.  Ознакомьтесь с программой из приложения 3. Изучите логику работы программы. Запустите программу и проанализируйте использование мьютекса.

6.  Ознакомьтесь с назначением и особенностями  применения семафоров для синхронизации процессов. Изучите синтаксис основных функций для работы с семафорами, а также программу из приложения 4, демонстрирующую использование семафоров.

7.  Составьте и выполните программу по индивидуальному заданию.

8.  Оформите отчет, проверьте свою подготовку по контрольным вопросам и защитите работу.

4.    КОНТРОЛЬНЫЕ   ВОПРОСЫ

1.  Поясните цели синхронизации процессов и потоков в многозадачных ОС.

2.  Приведите пример взаимной блокировки процессов (потоков).

3.  Кратко охарактеризуйте основные объекты синхронизации в ОС Windows.

4.  Что такое «сигнальное» и «свободное» состояние объекта синхронизации? Приведите примеры.

5.  Сформулируйте особенности событий как объектов синхронизации.

6.  Перечислите системные вызовы для работы с событиями.

7.  Составьте и выполните программу с использованием событий.

8.  Чем отличаются мануальные и единичные события?

9.  Что такое мьютекс?

10.  Поясните общие свойства и различия при использовании событий и мьютексов.

11.  Объясните синтаксис функции CreateMutex.

12.  Продемонстрируйте применение мьютекса в программе.

13.  Сформулируйте определение семафора.

14.  Поясните синтаксис системного вызова OpenSemaphore.

15.  Составьте пример программы с использованием семафора.

16.  Объясните различия между мьютексами и семафорами.

17.  Что общего в работе всех объектов синхронизации?

5.   ЛИТЕРАТУРА

1.  Сетевые операционные системы / В.Г.  Олифер, Н.А. Олифер. – СПб.: Питер, 2001,

     стр. 140 – 160.

2.  Вильямс А. Системное программирование в Windows 2000 для профессионалов. -

      СПб.: Питер, 2001,  стр.188 - 225

3.  Румянцев П.В. Азбука программирования в Win32  API. -  М.: Радио и связь  - Телеком, 1999, стр. 234 – 239.

Приложение  1.

//Программа демонстрирует работу с единичным событием

//Запустите программу без аргументов,

//программа перейдет в режим ожидания события

//Запустите после этого программу с любым параметром в командной строке

//Теперь программа функцией SetEvent() установит событие,

//на которое прореагирует запущенный ранее экземпляр программы.

//Последний выйдет из режима ожидания и закончит работу

//Тип приложения - Win32, Console

#include <windows.h>

#include <iostream.h>

void main(int argc, char argv[])

{

  //Создаем новое или открываем существующее событие

  HANDLE event = CreateEvent(NULL, FALSE, FALSE, "nevent");

  if (argc == 1)

  {

    cout<<"Waiting event!\n";

    cout.flush();

    //Определяем состояние события

    WaitForSingleObject(event, INFINITE);