Справочник от Автор24
Поделись лекцией за скидку на Автор24

Синхронизация. Критические секции. Объекты синхронизации и функции ожидания

  • 👀 230 просмотров
  • 📌 182 загрузки
Выбери формат для чтения
Загружаем конспект в формате pptx
Это займет всего пару минут! А пока ты можешь прочитать работу в формате Word 👇
Конспект лекции по дисциплине «Синхронизация. Критические секции. Объекты синхронизации и функции ожидания» pptx
СИНХРОНИЗАЦИ Я Крит ические сек ции  Для работы с объектами типа CRITICAL_SECTION используются следующие функции: // инициализация критической секции VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection); // вход в критическую секцию VOID EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection); // попытка войти в критическую секцию BOOL TryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection); // выход из критической секции VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection); // разрушение объекта критическая секция VOID DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection); #include #include using namespace std; DWORD WINAPI thread(LPVOID) { int i, j ; for (j = 0; j < 10; ++j) { // выводим строку чисел j for (i = 0; i < 10; ++i) { cout « j « ' ' « flush; Sleep(17); } cout « endl; return 0; } int main() { int i, j ; HANDLE hThread; DWORD IDThread; hThread=CreateThread(NULL, 0, thread, NULL, 0, &IDThread) ; if (hThread == NULL) return GetLastError(); for (j = 10; j < 20; ++j) { for (i = 0; i < 10; ++i) { // выводим строку чисел j cout « j « ‘ ‘ « flush; Sleep(17); } cout « endl; } // ждем, пока поток thread закончит свою работу WaitForSingleObject(hThread, INFINITE); return 0; } #include #include using namespace std; CRITICAL_SECTION cs; DWORD WINAPI thread(LPVOID) { int i,j; for (j = 0; j < 10; ++j) { // входим в крит ическую секцию EnterCriticalSection (&cs); for (i = 0; i < 10; ++i) { cout « j « ' '« flush; Sleep(7); } cout « endl; // вы ходим из крит ической секции LeaveCriticalSection(&cs); } return 0; } int main() { int i,j; HANDLE hThread; DWORD IDThread; // инициализируем критическую секцию InitializeCriticalSection(&cs); hThread=CreateThread(NULL, 0, thread, NULL, 0, &IDThread); if (hThread == NULL) return GetLastError(); for (j = 10; j < 20; ++j) { // входим в критическую секцию EnterCriticalSection(&cs); for (i = 0; i < 10; ++i) { cout « j « ' ' « flush; Sleep(7) ; } cout « endl; // вы ходим из критической секции LeaveCriticalSection(&cs); } // ж дем, пока поток thread закончит свою работ у WaitForSingleObject(hThread, INFINITE); // закры ваем критическую секцию DeleteCriticalSection(&cs); return 0; } Объект ы синхронизации и функции ож идания  В операционных системах Windows объектами синхронизации называются объекты ядра, которые могут находиться в одном из двух состояний: сигнальном (signaled) и несигнальном (nonsignaled). Объекты синхронизации могут быть разбиты на четыре класса. К первому классу относятся объекты синхронизации, т. е. те, которые служат только для решения задач синхронизации параллельных потоков:  мьютекс (mutex);  событие (event);  семафор (semaphore).  Ко второму классу объектов синхронизации относится ожидающий таймер (waitable timer), который переходит в сигнальное состояние по истечении заданного интервала времени.  К третьему классу синхронизации относятся объекты, которые переходят в сигнальное состояние по завершении своей работы:  процесс (process);  поток (thread).  К четвертому классу относятся объекты синхронизации, которые переходят в сигнальное состояние после получения сообщения об изменении содержимого объекта. К ним относятся:  изменение состояния каталога (change notification);  консольный ввод (console input).   Функции ожидания в Windows это такие функции, параметрами которых являются объекты синхронизации. Эти функции обычно используются для блокировки потоков. Для ожидания перехода в сигнальное состояние одного объекта синхронизации используется функция WaitForSingieObject, которая имеет следующий прототип: DWORD WaitForSingleObject( HANDLE hHandle, // дескриптор объект а DWORD dwMilliseconds // интервал ож идания в миллисекундах );   Для ожидания перехода в сигнальное состояние нескольких объектов синхронизации или одного из нескольких объектов синхронизации используется функция WaitForMuitipieObject, которая имеет следующий прототип: DWORD WaitForMultipleObjects( DWORD nCount, // количест во объектов CONST HANDLE *lpHandles, // массив дескрипторов объектов BOOL bWaitAll, // реж им ож идания DWORD dwMilliseconds // интервал ож идания в миллисекундах ); Мьютексы  Для решения проблемы взаимного исключения между параллельными потоками, выполняющимися в контекстах разных процессов, в операционных системах Windows используется объект ядра мьютекс. Слово мьютекс происходит от английского слова mutex, которое в свою очередь является сокращением от выражения mutual exclusion, что на русском языке значит "взаимное исключение". Мьютекс находится в сигнальном состоянии, если он не принадлежит ни одному потоку. В противном случае мьютекс находится в несигнальном состоянии. Одновременно мьютекс может принадлежать только одному потоку.  Создается мьютекс вызовом функции которая имеет следующий прототип: HANDLE CreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes, // ат рибут ы защит ы BOOL blnitialOwner, // начальны й владелец мьютекса LPCTSTR lpName // имя мьютекса ); CreateMutex, #include #include HANDLE hMutex; char IpszAppName [] = "С:\\ConsoleProcess.exe"; STARTUPINFO si; PROCESS_INFORMATION pi; // создаем мьютекс hMutex = CreateMutex(NULL, FALSE, "DemoMutex"); if (hMutex == NULL) { cout « "Create mutex failed." « endl; cout « "Press any key to exit." « endl; cin.get(); return GetLastError(); } ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); // создаем новый консольный процесс if (!CreateProcess(IpszAppName, NULL, NULL, NULL, FALSE, NULL, NULL, NULL, &si, &pi)) { cout « "The new process is not created." « endl; cout « "Press any key to exit." « endl; cin.get(); return GetLastError(); } // выводим на экран строки for (int j = 0; j < 10; ++j) { // захватываем мьютекс WaitForSingleObject(hMutex, INFINITE); for (int i = 0; i < 10; i++) { cout « j « ' ' « flush; Sleep(10); } cout « endl; // освобождаем мьютекс ReleaseMutex (hMutex) ; } // закрываем дескриптор мьютекса CloseHandle(hMutex); // ждем пока дочерний процесс закончит работу WaitForSingleObject (pi.hProcess, INFINITE) ; // закрываем дескрипторы дочернего процесса в текущем процессе CloseHandle (pi.hThread) ; CloseHandle(pi.hProcess); return 0; } #include #include int main() { HANDLE hMutex; int i , j ; // открываем мьютекс hMutex = OpenMutex(SYNCHRONIZE, FALSE,"DemoMutex"); if (hMutex == NULL) { cout « "Open mutex failed." « endl; cout « "Press any key to exit." « endl; cin.get(); return GetLastError(); for (j = 10; j < 20; j++) { // захватываем мьютекс WaitForSingleObject(hMutex, INFINITE); for (i = 0; i < 10; i++) { cout « j « ' ' « flush; Sleep(5); } cout « endl; // освобождаем мьютекс ReleaseMutex(hMutex); } // закрываем дескриптор объекта CloseHandle(hMutex); return 0; } Собы т ия  Событием называется оповещение о некотором выполненном действии. В программировании события используются для оповещения одного потока о том, что другой поток выполнил некоторое действие. Сама же задача оповещения одного потока о некотором действии, которое совершил другой поток, называется задачей условной синхронизации. В операционных системах Windows события описываются объектами ядра Events.  При этом различают два типа событий:  события с ручным сбросом;  события с автоматическим сбросом.  Создаются события вызовом функции CreateEvent, которая имеет следующий прототип: HANDLE CreateEvent( LPSECURITY_ATTRIBUTES IpSecurityAttributes, // ат рибут ы защиты BOOL bManualReset, // т ип собы т ия BOOL blnitialState, // начальное состояние собы тия LPCTSTR lpName // имя собы т ия );  Для перевода любого события в сигнальное состояние используется функция SetEvent, которая имеет следующий прототип: BOOL SetEvent( HANDLE hEvent // дескриптор собы тия ); #include #include HANDLE hOutEvent, hAddEvent; DWORD WINAPI thread (LPVOID) { for (int i = 0; i < 10; ++i) if (i == 4) { SetEvent(hOutEvent); WaitForSingleObject(hAddEvent, INFINITE); } return 0; } int main() { HANDLE hThread; DWORD IDThread; // создаем события с автоматическим сбросом hOutEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (hOutEvent == NULL) return GetLastError(); hAddEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (hAddEvent == NULL) return GetLastError(); // создаем поток thread hThread = CreateThread(NULL, 0, thread, NULL, 0, &IDThread); if (hThread == NULL) return GetLastError(); // ждем, пока поток thread выполнит половину работы WaitForSingleObject(hOutEvent, INFINITE); // выводим значение переменной cout « "A half of the work is done." « endl; cout « "Press any key to continue." « endl; cin.get(); // разрешаем дальше работать потоку thread SetEvent (hAddEvent) ; WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); CloseHandle(hOutEvent); CloseHandle(hAddEvent); cout « "The work is done." « endl; return 0; }  Доступ к существующему событию можно открыть с помощью функции CreateEvent или OpenEvent. HANDLE OpenEvent( DWORD dwDesiredAccess, // флаги дост упа BOOL blnheritHandle, // реж им наследования LPCTSTR lpName // имя собы тия ); Параметр dwDesiredAccess определяет доступ к событию и может быть равен любой логической комбинации следующих флагов:  ЕVENT_ALL_АСCESS — полный доступ;  Е VENT_MODIFY_SТАТЕ — модификация состояния;  SYNCHRONIZE — синхронизация.  Эти флаги устанавливают следующие режимы доступа к событию:  флаг Е VENT_ALL_АСCESS означает, что поток может выполнять над событием любые действия;  флаг EVENT_MODIFY_STATE означает, что поток может использовать функции SetEvent и ResetEvent для изменения состояния события;  флаг SYNCHRONIZE означает, что поток может использовать событие в функциях ожидания.  #include #include HANDLE hlnEvent; char IpEventName[ ] = "InEventName"; int main() { DWORD dwWaitResult; char szAppName[] = "D:\\ConsoleProcess.exe"; STARTUPINFO si; PROCESS_INFORMATION pi; // создем событие, отмечающее ввод символа hlnEvent = CreateEvent(NULL, FALSE, FALSE, IpEventName); if (hlnEvent == NULL) return GetLastError(); // запускаем процесс, который ждет ввод символа ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); if (!CreateProcess(szAppName, NULL, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) return 0; // закрываем дескрипторы этого процесса CloseHandle(pi.hProcess); CloseHandle(pi.hThread); // ждем оповещение о наступлении события о вводе символа dwWaitResult = WaitForSingieObject(hlnEvent, INFINITE); if (dwWaitResult != WAIT_OBJECT_0) return dwWaitResult; cout « "A symbol has got. " « endl; CloseHandie (hlnEvent) ; cout « "Press any key to exit."; cin.get(); return 0; } #include #include HANDLE hlnEvent; CHAR lpEventName[]="InEventName" ; int main () { char c; hlnEvent = OpenEvent (EVENT_MODIFY_STATE, FALSE, lpEventName); if (hlnEvent == NULL) { cout « "Open event failed." « endl; cout « "Input any char to exit." « endl; cin.get(); return GetLastError(); } cout « "Input any char: "; cin » c; // устанавливаем событие о вводе символа SetEvent(hlnEvent); // закрываем дескриптор события в текущем процессе CloseHandie(hlnEvent); cin.get(); cout << "Press any key to exit." << endl; cin.get(); return 0; } Семаф оры  Семафоры в операционных системах Windows описываются объектами ядра semaphores. Семафор находится в сигнальном состоянии, если его значение больше нуля. В противном случае семафор находится в несигнальном состоянии.  Создаются семафоры посредством вызова функции CreateSemaphore, которая имеет следующий прототип: HANDLE CreateSemaphore( LPSECURITY_ATTRIBUTES IpSemaphoreAttribute, // ат рибуты защит ы LONG llnitialCount, // начальное значение семаф ора LONG IMaximumCount, // максимальное значение семаф ора LPCTSTR lpName // имя семаф ора ); BOOL ReleaseSemaphore ( HANDLE hSemaphore, // дескриптор семаф ора LONG IReleaseCount, // полож ительное число, на которое увеличивается значение семаф ора LPLONG lpPreviousCount // преды дущее значение семаф ора ); HANDLE OpenSemaphore( DWORD dwDesiredAccess, // флаги доступа BOOL blnheritHandle, // режим наследования LPCTSTR lpName // имя события );     Параметр dwDesiredAccess определяет семафору и может быть равен любой комбинации следующих флагов: sEMAPHORE_ALL_ACCESS — полный семафору; SEMAPHORE_MODIFY_STATE — состояния семафора; SYNCHRONIZE — синхронизация. доступ к логической доступ к изменение #include #include volatile int a[10]; HANDLE hSemaphore; DWORD WINAPI thread(LPVOID) { for (int i = 0; i < 10; i++) { a [i] = i + 1; // отмечаем, что один элемент готов ReleaseSemaphore(hSemaphore,1,NULL); Sleep(500) ; } return 0; } int main() { int i; HANDLE hThread; DWORD IDThread; cout « "An initial state of the array: "; for (i = 0; i < 10; i++) cout « a[i] «' '; cout « endl; // создаем семафор hSemaphore=CreateSemaphore(NULL/ 0, 10, NULL); if (hSemaphore == NULL) return GetLastError(); // создаем поток, который готовит элементы массива hThread = CreateThread(NULL, 0, thread, NULL, 0, &IDThread); if (hThread == NULL) return GetLastError(); // поток main выводит элементы массива только после их подготовки потоком thread cout « "A final state of the array: "; for (i = 0; i < 10; i++) { WaitForSingleObject(hSemaphore, INFINITE); cout « a[i] « " \a" « flush; } cout « endl; CloseHandle(hSemaphore); CloseHandle(hThread); return 0; }
«Синхронизация. Критические секции. Объекты синхронизации и функции ожидания» 👇
Готовые курсовые работы и рефераты
Купить от 250 ₽
Решение задач от ИИ за 2 минуты
Решить задачу
Помощь с рефератом от нейросети
Написать ИИ

Тебе могут подойти лекции

Смотреть все 588 лекций
Все самое важное и интересное в Telegram

Все сервисы Справочника в твоем телефоне! Просто напиши Боту, что ты ищешь и он быстро найдет нужную статью, лекцию или пособие для тебя!

Перейти в Telegram Bot