Лабораторная работа
Синхронизация потоков в Windows
Категория: | Лабораторная работа |
Дисциплина: | Системное программирование |
Город: | Беларусь, Минск |
Учебное заведение: | БНТУ, ФИТР |
Стоимость работы: | бесплатный |
Оценка: | 10 |
Объем страниц: | 5 |
Год сдачи: | 2020 |
Дата публикации: | 04.02.2021 |
* Кроме файла с работой, также есть архив с дополнительными файлами.
Описание дополнительных файлов:
Исходный код программы
Фрагменты для ознакомления
Лабораторная работа № 1
СИНХРОНИЗАЦИЯ ПОТОКОВ В WINDOWS
Вариант 06
Цель работы:
Изучить основы синхронизации потоков в ОС Windows.
Изучаемые вопросы:
1. Блокирующие функции. Защищённый доступ к переменным.
2. Критические секции.
3. Ожидающие функции.
4. Взаимоисключения.
5. События.
6. Семафоры.
Постановка задачи:
Разработать многопоточное Win32-приложение, синхронизирующее работу трех вторичных потоков:
− первый помещает данные типа Type в хранилище на n элементов;
− второй сортирует данные в хранилище;
− третий извлекает данные из хранилища и визуализирует их.
*Тип хранилища и тип данных задается преподавателем.
Ход выполнения работы:
Блокирующие функции. Защищённый доступ к переменным
Для корректного изменения значения булевской переменной, использовал функцию семейства 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);
Результаты работы программного обеспечения:
