Лабораторная работа

Синхронизация потоков в Windows

Категория:

Лабораторная работа

Дисциплина:

Системное программирование

Город:

Беларусь, Минск

Учебное заведение:

БНТУ, ФИТР

Стоимость работы:

бесплатный

Оценка: 10
Объем страниц: 5
Год сдачи: 2021
Дата публикации: 04.02.2021

* Кроме файла с работой, также есть архив с дополнительными файлами.

Описание дополнительных файлов:

Исходный код программы

Фрагменты для ознакомления

Лабораторная работа № 1

СИНХРОНИЗАЦИЯ ПОТОКОВ В WINDOWS

Вариант 06

 

Цель работы:

Изучить основы синхронизации потоков в ОС Windows.

Изучаемые вопросы:

1. Блокирующие функции. Защищённый доступ к переменным.

2. Критические секции.

3. Ожидающие функции.

4. Взаимоисключения.

5. События.

6. Семафоры.

 

Постановка задачи:

Разработать многопоточное Win32-приложение, синхронизирующее работу трех вторичных потоков:

− первый помещает данные типа Type в хранилище на элементов;

− второй сортирует данные в хранилище;

− третий извлекает данные из хранилища и визуализирует их.

*Тип хранилища и тип данных задается преподавателем.

 

Ход выполнения работы:

Блокирующие функции. Защищённый доступ к переменным

Для корректного изменения значения булевской переменной, использовал функцию семейства Interlocked-функций:

InterlockedExchange((PLONG)&fCompletion, TRUE);

 

Критические секции

Чтобы только один поток смог получить доступ к определённому ресурсу (структуре structArrayFloat) использовал критическую секцию:

CRITICAL_SECTION cs;

Для инициализации критической секции и счётчика циклов использовал:

if (!InitializeCriticalSectionAndSpinCount(&cs, WAITINGTIME)) 

{

                     MessageBox(hWND, TEXT("A memory allocation failed"), TEXT("Error"), MB_OK);

                     return FALSE;

}

EnterCriticalSection(&cs);

for (int i = 0; i < fArray.size; i++)

{

         fArray.arrayFloat[i] = uid(gen);

}

LeaveCriticalSection(&cs); //уменьшает счетчик числа захватов ресурса вызов. потоком на 1

И после завершения работы потоков со структурой CRITICAL_SECTION, удаляем её:

DeleteCriticalSection(&cs);

 

Ожидающие функции

Wait-функции позволяют потоку в любой момент приостановиться и ждать освобождения какого-либо объекта ядра. 

Ожидание в течение произвольного периода времени:

WaitForSingleObject(hSemaphore, WAITINGTIME);          // WAITINGTIME = 4000

Бесконечное ожидание:

WaitForSingleObject(g_Event, INFINITE);

WaitForSingleObject(hMutex, INFINITE);

 

Взаимоисключения

Для обеспечения взаимоисключающего доступа к ресурсу использовал объекты ядра «мьютексы».

// объект-мьютекс не принадлежит ни одному из потоков (свободном состоянии)

hMutex = CreateMutex(NULL, FALSE, TEXT("my_mutex_LR1"));

WaitForSingleObject(hMutex, INFINITE);

CloseHandle(hMutex);

 

События

Для уведомления одного потока о завершении операции в другом потоке использовал события:

g_Event = CreateEvent(NULL, TRUE, FALSE, TEXT("my_event_LR1"));

В данном случае создаётся объект «событие со сбросом вручную (fManualReset = TRUE) в занятом состоянии (fInitialState = FALSE)».

Для освобождения события и тут же перевода его обратно в занятое состояние использовал:

PulseEvent(g_Event);

Что равнозначно последовательному вызову SetEvent и ResetEvent.

WaitForSingleObject(g_Event, INFINITE);

CloseHandle(g_Event);

 

Семафоры

Для учёта ресурса, который используется потоками создавал семафор со счетчиком максимального числа ресурсов равным 1, при этом изначально ни один ресурс не доступен (lInitiа1Соипt = 0):

hSemaphore = CreateSemaphore(NULL, 0, 1, TEXT("my_semaphore_LR1"));

Для увеличения значение счетчика текущего числа ресурсов, вызывал функцию:

ReleaseSemaphore(hSemaphore, 1, &prevCount); 

Где третий параметр возвращает исходное значение счётчика.

WaitForSingleObject(hSemaphore, WAITINGTIME);

CloseHandle(hSemaphore);

 

Результаты работы программного обеспечения:

246