Цель работы
Изучение способа организации критических секций с
использованием группы 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).
Комментариев нет:
Отправить комментарий