30515

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

Доклад

Математика и математический анализ

При создании многопоточных приложений необходимо контролировать взаимодействие отдельных потоков. Большинство ошибок при работе с потоками возникает из-за того, что во время работы приложения различные потоки пытаются обратиться к одним и тем же данным. Для предотвращения подобной ситуации в ОС Windows (как впрочем и в других операционных системах) существуют средства синхронизации, которые позволяют контролировать доступ к разделяемым ресурсам.

Русский

2013-08-24

25.71 KB

13 чел.

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

НА ДОСКЕ:

1) single-object

DWORD WaitForSingleObject (

 HANDLE hHandle,

 DWORD dwMilliseconds

);

2) multiple-object

DWORD WaitForMultipleObjects(

 DWORD nCount,

 const HANDLE* lpHandles,

 BOOL bWaitAll,

 DWORD dwMilliseconds

);

3) сигнализирующие (alertable).

На доске особо рисовать нечего. Можем схематично показать занятость и свободность объекта ядра. Либо предоставить на обозрение публике куски кода.

В основную часть терминология с кратким объяснением.

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

ВЫСТУПЛЕНИЕ:

При создании многопоточных приложений необходимо контролировать взаимодействие отдельных потоков. Большинство ошибок при работе с потоками возникает из-за того, что во время работы приложения различные потоки пытаются обратиться к одним и тем же данным. Для предотвращения подобной ситуации в ОС Windows (как впрочем и в других операционных системах) существуют средства синхронизации, которые позволяют контролировать доступ к разделяемым ресурсам.

Для обеспечения синхронного взаимодействия потоков создаются объекты синхронизации, используемые в так называемых wait-функциях, которые приостанавливают выполнение потока до тех пор, пока не будет выполнено определенное условие (оно зависит от типа wait-функции).

В Windows существует три группы wait-функций:

1) single-object

К этой группе относится функция WaitForSingleObject(), которая приостанавливает поток до освобождения заданного объекта синхронизации.

DWORD WaitForSingleObject(

 HANDLE hHandle,

 DWORD dwMilliseconds

);

Параметр hHandle - это дескриптор объекта синхронизации.

Параметр dwMilliseconds указывает время, по истечении которого функция завершается, даже если объект синхронизации не освободился. В этом случае функция возвращает значение WAIT_TIMEOUT.

2) multiple-object

Функции этой группы позволяют потоку ждать освобождения или нескольких объектов синхронизации, или одного из них. К этой группе относится функция WaitForMultipleObjects().

DWORD WaitForMultipleObjects(

 DWORD nCount,

 const HANDLE* lpHandles,

 BOOL bWaitAll,

 DWORD dwMilliseconds 

);

Параметр nCount указывает количество дескрипторов объектов, содержащихся в массиве, на который указывает параметр lpHandles. Максимально возможное число дескрипторов объектов равно константе MAXIMUM_WAIT_OBJECTS.

Параметр lpHandles - указатель на массив, в котором содержаться дескрипторы объектов синхронизации.

Параметр bWaitAll - если этот параметр равен TRUE, то функция возвращает управление потоку, когда освобождаются все объекты синхронизации, дескрипторы которых содержатся в массиве. Если параметр равен FALSE, то функция завершается при освобождении любого из объектов.

Параметр dwMilliseconds указывает время, по истечении которого функция завершается, даже если объект синхронизации не освободился. В этом случае функция возвращает значение WAIT_TIMEOUT.

3) сигнализирующие (alertable).

При вызове любой wait-функции можно задавать время ожидания, по истечении которого функция завершается, не дождавшись выполнения заданного условия, и возвращает потоку значение WAIT_TIMEOUT.

Объекты синхронизации:

  1.  Семафор (Semaphore)
  2.  Мьютекс (Mutex)
  3.  Событие (Event)
  4.  Таймер (Timer)
  5.  Критическая секция (Critical Section)

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

Критическая секция — часть программы, в которой есть обращение к совместно используемым данным. При нахождении в критической секции двух (или более) процессов, возникает состояние «гонки» («состязания»). Для избежания данной ситуации необходимо выполнение четырех условий:

  1.  Два процесса не должны одновременно находиться в критических областях.
  2.  В программе не должно быть предположений о скорости или количестве процессоров.
  3.  Процесс, находящийся вне критической области, не может блокировать другие процессы.
  4.  Невозможна ситуация, в которой процесс вечно ждет попадания в критическую область.

Критическая секция — объект синхронизации потоков, позволяющий предотвратить одновременное выполнение некоторого набора операций (обычно связанных с доступом к данным) несколькими потоками. Критическая секция выполняет те же задачи, что и мьютекс.

Между мьютексом и критической секцией есть терминологические различия, так процедура, аналогичная захвату мьютекса, называется входом в критическую секцию, снятию блокировки мьютекса — выходом из критической секции.

Процедура входа и выхода из критических секций обычно занимает меньшее время, нежели аналогичные операции мьютекса, что связано с отсутствием необходимости обращаться к ядру ОС.

В операционных системах семейства Microsoft Windows разница между мьютексом и критической секцией в том, что мьютекс является объектом ядра и может быть использован несколькими процессами одновременно, критическая секция же принадлежит процессу и служит для синхронизации только его потоков.

Критические секции Windows имеют оптимизацию, заключающуюся в использовании атомарно изменяемой переменной наряду с объектом «событие синхронизации» ядра. Захват критической секции означает атомарное увеличение переменной на 1. Переход к ожиданию на событии ядра осуществляется только в случае, если значение переменной до захвата было уже больше 1, то есть происходит реальное «соревнование» двух или более потоков за ресурс.

Таким образом, при отсутствии соревнования захват/освобождение критической секции обходятся без обращений к ядру.

Кроме того, захват уже занятой критической секции до обращения к ядру какое-то небольшое время ждёт в цикле опроса переменной, и, если переменная становится равной 0, то захват происходит без обращений к ядру.

Сходный объект в ядре Windows называется FAST_MUTEX (ExAcquire/ReleaseFastMutex). Он отличается от критической секции отсутствием поддержки рекурсивного повторного захвата тем же потоком.

Аналогичный объект в Linux называется фьютекс.

Функции ожидания

Объекты синхронизации используются совместно с функциями ожидания. Эти функции связываются с одним или несколькими синхронизирующими объектами и ждут, когда эти объекты перейдут в сигнальное состояние. Тем самым выполнение процесса может быть приостановлено до тех пор, пока в системе не произойдёт некоторое событие.

Ожидание одного события может быть организовано вызовом функции WaitForSingleObject:

DWORD WaitForSingleObject(

 IN HANDLE hHandle,

 IN DWORD dwMilliseconds

);

Параметр hHandle - дескриптор объекта синхронизации.

Параметр dwMilliseconds - время ожидания (тайм-аут) в миллисекундах.

  1.  Если объект, на который указывает hHandle, в данный момент находится в несигнальном состоянии, функция ждёт, пока он перейдёт в сигнальное состояние, или пока не закончится время ожидания.
  2.  Если объект в момент вызова функции находится в сигнальном состоянии, функция возвращается немедленно.
  3.  Если возвращённое функцией значение равно WAIT_TIMEOUT, это свидетельствует о том, что время ожидания истекло, а объект так и не перешёл в сигнальное состояние. Значение WAIT_OBJECT_0 свидетельствует о том, что объект сразу был в сигнальном состоянии или перешёл в это состояние во время ожидания. Возвращённое функцией WaitForSingleObject значение WAIT_ABANDONED возможно только для мьютексов и свидетельствует о том, что мьютекс освободился вследствие окончания выполнения владевшего им потока. Подробнее это будет рассмотрено в статье "Мьютексы". Значение WAIT_FAILED свидетельствует об ошибке выполнения функции.
  4.  Если параметр dwMilliseconds задан равным 0, функция тестирует состояние объекта и немедленно возвращается, независимо от состояния объекта.
  5.  Если dwMilliseconds = INFINITE, функция возвращается только при переходе объекта в сигнальное состояние. Такое значение параметра dwMilliseconds надо задавать с большой осторожностью при этом надо быть абсолютно уверенным, что рано или поздно объект перейдёт в сигнальное сотояние. В противном случае приложение "зависнет".

Перед возвращением функция WaitForSingleObject изменяет состояние объекта, например, захватывает мьютекс, уменьшает число семафора на 1 и т.д.

Ожидание нескольких синхронизирующих объектов может быть организовано функцией WaitForMultipleObjects:

DWORD WaitForMultipleObjects (

IN DWORD nCount,                             

IN CONST HANDLE *lpHandles,

                            IN BOOL bWaitAll,

                            IN DWORD dwMilliseconds

);

Параметр lpHandles является указателем на массив дескрипторов объектов синхронизации.

Параметр nCount определяет число дескрипторов в этом массиве, используемых функцией.

Параметр bWaitAll определяет логику ожидания.

  1.  При bWaitAll = true функция ждёт, пока все объекты окажутся в сигнальном состоянии.
  2.  При bWaitAll = false функция возвращается, если в сигнальном состоянии находится хотя бы один объект. В этом случае возвращаемое функцией значение указывает, какой именно объект находится в этом состоянии.

Параметр dwMilliseconds определяет время ожидания и всё, сказанное выше об аналогичном параметре функции WaitForSingleObject, относится и к данной функции.

Функция работает аналогично функции WaitForSingleObject, отличаясь только возвращаемыми значениями.

  1.  При bWaitAll = true функция возвращает значения WAIT_OBJECT_0, WAIT_TIMEOUT, WAIT_ABANDONED_0 или WAIT_FAILED. Смысл этих значений рассматривался ранее.
  2.  При bWaitAll = false возможные значения WAIT_TIMEOUT, WAIT_FAILED, от WAIT_OBJECT_0 до WAIT_OBJECT_0 + nCount – 1 и от WAIT_ABANDONED_0 до WAIT_ABANDONED_0 + nCount - 1. Разности возвращённого результата - WAIT_OBJECT_0 или возвращённого результата - WAIT_ABANDONED_0 дают индекс того объекта в массиве lpHandles, который вызвал завершение выполнения функции.

 

А также другие работы, которые могут Вас заинтересовать

62539. Звери - млекопитающие 210.75 KB
  Ход урока. Всех пугала всех глотала А теперь в котёл попала щука Как вы думаете кто в этой группе лишний щука Почему вы так думаете О ком же мы будем сегодня говорить Мы узнаем что все звери млекопитающие.
62540. Разнообразие растений и животных 32.91 KB
  Личностные УУД положительное отношение к учебной деятельности. Личностные УУД проявление положительного отношения к познавательной деятельности интереса к учебному материалу. Регулятивные УУД планирование своего действия в соответствии с поставленной задачей и условиями ее реализации.
62543. О МАМЕ И О ПАПЕ 24.55 KB
  Цель урока: Дать первоначальные представления о православных основах семьи. Задачи урока: Познакомить с проявлением православных традиций в семье. Познакомить с Владимировской иконой Божией Матери.
62544. Основные понятия алгебры логики 23.1 KB
  Высказывание это фомулировка своего понимания окружающего мира. Высказывание является повествовательным преждложением в котором что-либо отрицается или утверждается. По поводу высказывание можно сказать истинно оно или ложно.
62545. Диффузия 24.1 KB
  Цели урока: познакомить учащихся с диффузией в жидкостях, газах и твердых телах; научить объяснять явление диффузии и скорость ее протекания в зависимости от температуры тела; развитие самостоятельности учащихся в процессе работы...
62546. Действия с информацией. Хранение информации 24.73 KB
  Цель урока: акцентировать внимание учащихся на действиях с информацией информационных процессах; познакомить со способами хранения информации. Изучением всевозможных способов передачи хранения и обработки информации.
62547. Открытие протона и нейтрона 960.86 KB
  Учитель записывает под диктовку на доску. Учитель вносит дополнения в список на доске. Учитель дополняет список на доске.