
Лабораторна робота № 4.
Тема: Синхронізація потоків у Windows.
Мета: Ознайомитись з методикою синхронізації потоків за допомогою критичних секцій.
Теоретичні відомості.
Синхронізація потоків і процесів полягає в узгодженні їх швидкостей шляхом призупинення потоку до настання деякої події і подальшій його активізації при настанні цієї події.
На практиці найчастіше зустрічаються такі випадки синхронізації:
1. Умовна синхронізація. (потік чекає сповіщення про виконання деякої логічної умови)
2. Взаємне виключення. (відбувається безумовне виконання потоком безперервної дії до моменту перехоплення управління іншим потоком).
Потреба в синхронізації потоків виникає тільки в мультипрограмній ОС і пов'язана зі спільним використанням апаратних і інформаційних ресурсів комп'ютера. Синхронізація необхідна для виключення одночасного доступу до ресурсу при обміні даними між потоками, поділі даних, при доступі до процесора і пристроїв введення-виведення.
Нехтування питаннями синхронізації в багатопотоковій системі може привести до неправильного вирішення задачі або навіть до краху системи.
Для синхронізації потоків у Windows використовуються об’єкти:
• м’ютекс (mutex);
• подія (event);
• семафор (semaphore).
Об’єкти можуть бути в одному з двох станів:
сигнальному (означає, що ресурс вільний і потік готовий до виконання)
несигнальному (на даний момент ресурс використовується іншим потоком)
У цій роботі розглянемо об’єкт «подія».
Подією називається сповіщення про деяку виконану дію. У програмуванні події використовуються для сповіщення одного потоку про те, що інший потік виконав деяку дію. Такі задачі відносяться до задач умовної синхронізації. У операційних системах Windows події описуються об'єктами ядра Events.
Створюються події викликом функції CreateEvent, яка має наступний прототип:
HANDLE CreateEvent( LPSECURITY_ATTRIBUTES lpSecurityAttributes, // атрибути захисту BOOL bManualReset, // тип події BOOL bІnitialState, // початковий стан події LPCTSTR lpName // ім'я події ); |
bManualReset – тип події. Якщо значення параметра рівне true, то створюється подія з ручним скиданням, інакше - з автоматичним скиданням.
Різниця між цими типами подій полягає в тому, що подія з ручним скиданням можна перевести в несигнальному стан тільки за допомогою виклику функції ResetEvent, а подія з автоматичним скиданням переходить в несигнальний стан як за допомогою функції ResetEvent, так і за допомогою функції очікування.
bІnitialState – початковий стан події. Якщо значення параметра binitiaistate рівне true, то початковий стан події є сигнальним, інакше - несигнальним.
lpName – задає ім'я події, яка дозволяє звертатися до неї з потоків, що виконуються в різних процесах. Цей параметр може бути рівний null, тоді створюється безіменна подія.
У разі вдалого завершення функція CreateEvent повертає дескриптор події, а у разі невдачі — значення null. Якщо подія із заданим ім'ям вже існує, то функція CreateEvent повертає дескриптор цієї події, а функція GetLastError, викликана після функції CreateEvent, поверне значення error_already_exists.
Для встановлення будь-якої події в сигнальний стан використовується функція SetEvent, яка має наступний прототип:
BOOL SetEvent( HANDLE hEvent // дескриптор події ); |
При успішному завершенні ця функція повертає ненульове значення, а у разі невдачі false.
Постановка задачі:
Використовуючи об’єкти синхронізації реалізувати наступні задачі для роботи з потоками:
1) Написати програму для одночасного опрацювання матриці двома потоками.
Перший потік підноситиме кожен від’ємний елемент масиву до квадрату, другий - знаходитиме кількість рядків, у яких немає жодного від’ємного елемента.
2) Правильно розставити події для синхронізації потоків.
3) Порівняти результати з використанням синхронізації та без використання.