Лабораторная работа: Синхронизация нитей с использованием событий и Interlocked-функций

Цель работы

Изучение способа организации критических секций с использованием группы Interlocked-функций. Изучение способа синхронизации процессов и нитей с использованием событий (Events).

Список используемых системных вызовов

CreateEvent, SetEvent, ResetEvent, PulseEvent, CloseHandle, InterlockedExchange, InterlockedIncrement, InterlockedDecrement, InterlockedCompareExchange, InterlockedExchangeAdd, InitializeCriticalSection, EnterCriticalSection, TryEnterCriticalSection, LeaveCriticalSection, DeleteCriticalSection, WaitForSingleObject, WaitForMultipleObjects.

Методические указания

Для данной работы критическим ресурсом будет выступать окно консольного приложения.
Группа Interlocked-функций позволяет производить атомарные операции над двойным словом данных. С помощью функции InterlockedExchange организуются критические секции, как показано ниже:
// Инициализация
static LONG volatile Status = 0;
...
// Вход
while (1 == InterlockedExchange(&Status, 1))
{
Sleep(20);
}
// Критическая секция
Status = 0;
// Конец критической секции
Критическую секцию можно организовать и с использованием структуры CRITICAL_SECTION. Вариант критической секции показан ниже:
// Инициализация
CRITICAL_SECTION cs;
InitializeCriticalSection(&cs);
...
// Вход
EnterCriticalSection(&cs);
// Критическая секция
LeaveCriticalSection(&cs);
// Конец критической секции
...
// Деинициализация
DeleteCriticalSection(&cs);
Синхронизацию нитей можно осуществлять с помощью событий (Events). Для создания объекта события используется функция CreateEvent. События бывают с ручным и автоматическим сбросом. События с автоматическим сбросом переходят в несигнальное состояние сразу после возврата из ожидающей WaitFor-функции. События с ручным сбросом необходимо сбрасывать с помощью функции ResetEvent. Перевод события в сигнальное состояние осуществляется с помощью функции SetEvent. После завершения работы событием необходимо закрыть дескриптор события с помощью функции CloseHandle.

Задание

  Имеется 3 нити. Две из них производят инкремент переменной на 1. Одна – декремент на 2. Работа с переменной должна осуществляться с помощью критической секции на основе CRITICAL_SECTION. Вывести на экран текущее значение переменной и крайние значения.
                                                           Листинг программы.
#include <stdio.h>
#include <windows.h>

DWORD WINAPI MyThread(LPVOID lpParam);

CRITICAL_SECTION g_cs;

static int  InUse = 1;
void main()
{
            HANDLE hThread;
            int k=3;
            InitializeCriticalSection(&g_cs);
            //порождаем k потоков
            while(k>0)
            {
                        hThread = CreateThread(NULL, 0, MyThread,
                                   (LPVOID)k, 0, NULL);
                        if(hThread==NULL)
                        {
                                   printf("\nError create thread!!!");
                                   exit(0);
                        }
                        CloseHandle(hThread);
                        k--;
            }
            //вывод продолжается до тех пор, пока не нажата клавиша ENTER
            while(!getchar()){;}
            DeleteCriticalSection(&g_cs);

}


DWORD WINAPI MyThread(LPVOID lpParam)
{
            int k = (int)lpParam;

            while(1)
            {
                        //ожидаем освобождения ресурса
                        EnterCriticalSection(&g_cs);
                        if(k==3)
                        {
                                   printf("\nWINDOW %d", k);
                                   printf("\nCurrent: %d", InUse);
                                   InUse=InUse-2;
                                   printf("\n Current -2: %d", InUse);
                                   Sleep(20);
                        }
                        else
                        {
                                  
                                   //после захвата ресурса выводим свой символ
                                   printf("\nWINDOW %d", k);
                                   printf("\nCurrent: %d", InUse);
                                   InUse++;
                                   printf("\n Current +1: %d", InUse);
                                   Sleep(20);
                        }
                        //освобождаем ресурс после использования
                        LeaveCriticalSection(&g_cs);
            }
            return 0;
}

Вывод: изучили способы организации критических секций с использованием группы Interlocked-функций, а также изучили способ синхронизации процессов и нитей с использованием событий (Events).

Комментариев нет:

Отправить комментарий