Объекты критических участковкода

Как уже упоминалось ранее, объект критичного участка кода — это участок программного кода, который всякий раз должен производиться только одним потоком; параллельное выполнение этого участка несколькими потоками может приводить к непредсказуемым либо неправильным результатам.

В качестве обычного механизма реализации и внедрения на практике концепции критичных участков кода Windows предоставляет объект CRITICAL Объекты критических участковкода_SECTION.

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

Для инициализации и удаления переменной типа CRITICAL_SECTION употребляются, соответственно, функции InitializeCriticalSection и DeleteCriticalSection:

VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection)

VOID DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection Объекты критических участковкода)

Функция EnterCriticalSection перекрывает поток, если на данном критичном участке кода находится другой поток. Ожидающий поток разблокируется после того, как другой поток выполнит функцию LeaveCriticalSection. Молвят, что поток получил права владения объектом CS, если произошел возврат из функции EnterCriticalSection, тогда как для уступки прав владения употребляется функция LeaveCriticalSection. Всегда Объекты критических участковкода смотрите за своевременной переуступкой прав владения объектами CS; несоблюдение этого правила может привести к тому, что другие потоки будут пребывать в состоянии ожидания в течение неопределенного времени даже после окончания выполнения потока-владельца.

Мы нередко будем гласить о перекрытии и разблокировании объектов CS, а вхождение в CS будет означать то Объекты критических участковкода же, что и блокирование CS.

VOID EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection)

VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection)

Поток, обладающий объектом CS, может повторно войти в тот же CS без его блокирования; это значит, что объекты CRITICAL_SECTION являются рекурсивными (recursive). Поддерживается счетчик вхождений в объект CS, и потому поток должен покинуть Объекты критических участковкода данный CS столько раз, сколько было вхождений в него, чтоб разблокировать этот объект для других потоков. Эта возможность возможно окажется полезной для реализации рекурсивных функций и обеспечения неопасного многопоточного выполнения функций общих (разделяемых) библиотек.

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

Для возврата из функции EnterCriticalSection не существует конечного интервала ожидания; другие потоки будут блокированы на неопределенное время, пока поток, обладающий объектом CS, не покинет его. Но, используя функцию TryEnterCriticalSection, можно тестировать (опросить) CS, чтоб проверить, не обладает ли им другой поток.

BOOL TryEnterCriticalSection(LPCRITICAL Объекты критических участковкода_SECTION lpCriticalSection)

Возврат функцией TryEnterCriticalSection значения True значит, что вызывающий поток заполучил права владения критичным участком кода, тогда как возврат значения False гласит о том, что данный критичный участок кода уже принадлежит другого потока.

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

Настройка спин-счетчика

Обычно, если в итоге выполнения функции EnterCriticalSection поток обнаруживает, что объект CS уже принадлежит другому сгустку, он заходит в ядро Объекты критических участковкода и остается блокированным до того времени, пока не освободится объект CRITICAL_SECTION, что просит определенного времени. Но в SMP-системах вы сможете востребовать, чтоб поток повторил попытку овладеть объектом CS, до того как блокироваться, так как существует возможность того, что поток, обладающий CS, производится на другом микропроцессоре и Объекты критических участковкода в хоть какой момент может высвободить CS. Это возможно окажется полезным для увеличения производительности, если меж потоками наблюдается высочайшая состязательность за право владения единственным объектом CRITICAL_SECTION. Воздействие упомянутых причин на производительность дискуссируется дальше в этой и следующих главах.

Для опции счетчика занятости, либо спин-счетчика (spin-count), предусмотрены две Объекты критических участковкода функции, одна из которых, SetCriticalSectionSpinCount, обеспечивает динамическую настройку счетчика, а 2-ая, InitializeCritical-SectionAndSpinCount, выступает в качестве подмены функции Initialize-CriticalSection. Настройка спин-счетчика рассматривается в главе 9.


obektivnie-predposilki-strategii-povisheniya-effektivnosti-gosudarstva.html
obektivnie-priznaki-sostava-prestupleniya.html
obektivnie-vrachebnie-oshibki.html