Лабораторная работа № 3 средства синхронизации потоков и тупики
Цель работы -практическое знакомство с методами синхронизации двух потоков одного процесса с помощью критических секций, мьютексов, семафоров и событий, а также средствами анализа тупиковых ситуаций.
1. Краткие теоретические сведения
В случае одновременной модификации глобальной переменной двумя и более потоками возможна потеря выполненных изменений. Для правильной работы приложений с несколькими потоками необходимо обеспечить поочередный доступ потоков к операторам программы, выполняющим изменение и запись значений переменной в память (критическим участкам).
Только один процесс должен иметь возможность изменять и записывать значения глобальных переменных.
Участок программного кода, в котором поток имеет возможность обращаться к общему неразделяемому ресурсу с целью его модификации, называется критическим участком.
Правильная работы программы, содержащей критические участки, возможна только при поочередном выполнении потоками программы критических участков.
Для решения этой задачи могут использоваться простые средства – критические секции, обеспечивающие поочередный доступ к критическим участкам потоков одного процесса, и более сложные средства – Mutex (mutually exclusive – взаимно - исключающий) - мьютексы,решающие такую же задачу для потоков, созданныхразличными процессами. Кроме того, задача обеспечения поочередного доступа потоков к критическим участкам может быть решена с помощью универсальных средств синхронизации -семафоров и событий.
В рассмотренном ниже приложении два потока увеличивают значение глобальной переменной Global от начального значения 100 на 1 при каждом выполнении цикла. Число повторений цикла каждого потока равно 12, результаты увеличения переменной Global выводятся на экран с помощью двух компонентов ListBox.
При правильной работе приложения конечным значением переменной должно быть число 100+12+12=124. Однако без специальных мер такого значения получить в общем случае не удается, так как потоки " мешают ” друг другу.
Критические секции
Критические секции– средство синхронизации потоков одного приложения. Критические секции обеспечивают поочередный доступ потоков к критическим участкам программы. Для использования критической секции ее необходимосоздать, то есть объявить глобальную переменнуюsect1 типаTRTLCriticalSectionи инициализировать ее с помощью вызова функции
initializeCriticalSection(sect1)
Для обеспечения поочередного доступа потоков к критическому участку в начале критического участка вызывается функция
EnterCriticalSection (имя секции), а в конце – функция
LeaveCriticalSection (имя секции).
После окончания использования критической секции она уничтожается вызовом функции DeleteCriticalSection(sect1).
Мьютексы
Мьютекс– объект ядра, используемый как средство синхронизации доступа потоков одного или нескольких приложений к критическому участку.
Мьютекс создается с помощью функции
Createmutex (
lpMutexAttributes : LPSECURITY_ATTRIBUTES; // обычно равен nil указатель на атрибут
// безопасности
False ; // принадлежность создавшему потоку
lpSemaphoreAttributes : LPSECURITY_ATTRIBUTES // обычно равен nil
) : Thandle ;
В начале критического участка вызывается функция
Waitforsingleobject (hmut, infinite); а в конце - функция
Releasemutex (hmut) – освобождение критического участка (мьютекса).
Удаление объекта ядра Mutexвыполняет функция
CloseHandle (hmut).
Семафоры
Семафор– объект ядра, используемый как универсальное средство управления ресурсами. Как правило, семафор используется для учета неразделяемых ресурсов. В данной работе семафор должен использоваться для синхронизации двух конкурирующих потоков одного приложения.
Семафор создается с помощью функции
CreateSemaphore(
lpSemaphoreAttributes : LPSECURITY_ATTRIBUTES, // обычно равен nil
Count : integer; // начальное значение счетчика свободных ресурсов
MaximumCount : integer; // максимальное количество свободных ресурсов
lpName : LPCTSTR // имя семафора - обычно nil
) : Thandle ;
В начале критического участка вызывается функция
Waitforsingleobject (hmut, infinite); а в конце - функция
ReleaseSemaphore (hsem, 1, nil) - освобождение критического участка (семафора).
Удаление объекта ядра Semsphoreвыполняет функция
CloseHandle(hmut).