Критическое изменение раздела поведения в Windows 2003 SP1 - PullRequest
3 голосов
/ 27 апреля 2011

Сегодня я сталкивался с этим в MSDN :

"Начиная с Windows Server 2003 с пакетом обновления 1 (SP1), потоки ожидания на критическом участке не получить критический раздел на первым пришел, первым обслужен. это изменение увеличивает производительность значительно для большей части кода. Тем не мение, некоторые приложения зависят от первого, первоочередной (FIFO) заказ и может выступать плохо или вообще не текущие версии Windows (для Например, приложения, которые были используя критические секции в качестве Скорость-ограничитель). Чтобы убедиться, что ваш код продолжает работать правильно, вы возможно, потребуется добавить дополнительный уровень синхронизации. Например, предположим, у вас есть продюсерская ветка и потребительская нить, использующая объект критической секции для синхронизации их работа. Создать два объекта события, один для каждого потока, чтобы использовать, чтобы сигнализировать что оно готово для другого потока продолжать. Потребительская нить будет подождите, пока производитель не подаст сигнал событие до входа в критическую раздел, и продюсер темы будет ждать, пока поток потребителя не выдаст сигнал его событие, прежде чем войти в критическую раздел. После того, как каждая нить покидает критический раздел, он сигнализирует о своем событии освободить другой поток. "

Сначала я подумал WTF ?! - Я всегда предполагал, что потоки получат критическую секцию в том порядке, в котором они пытались ее получить. Хотя это кажется странно большим изменением в поведении пакета обновления, этот пакет был предназначен для серверной версии Windows, и в то время, как я считаю, находилась в стадии разработки.

В любом случае, в этом есть небольшой смысл - таким образом следующий ожидающий поток, в который вращается планировщик, будет следующим, который получит критический раздел следующим, по крайней мере, я предполагаю. Это единственное, что имеет смысл, если только они не решили сделать случайный выбор для развлечения;).

Тем не менее, это предположение, которое я сделал и сейчас оцениваю свой код, чтобы убедиться, что ни в одном случае FIFO не является проблемой.

У кого-нибудь были проблемы с этим? Хотя порядок потоков, получающих критическую секцию, не ГАРАНТИРУЕТСЯ быть FIFO, разве это обычно не FIFO? Если нет обычно FIFO (или близко к FIFO), кто-нибудь знает, как долго поток может ожидать сильно оспариваемого критического раздела? Если это поток с низким приоритетом, означает ли это, что он может продолжать ждать почти бесконечно, если всегда есть поток с более высоким приоритетом, пытающийся получить критическую секцию (даже если поток с низким приоритетом был давно следующим в строке, если FIFO придерживался )? Существует ли предохранитель, предотвращающий этот сценарий, или обязательна опора на вторичный объект синхронизации?

Конечно, это действительно имеет значение только в действительно сильно оспариваемом критическом разделе.

Я не знаю, может быть, я делаю слишком много ... но что-то беспокоит меня об этом. Любое понимание приветствуется. Спасибо;)

Ответы [ 2 ]

1 голос
/ 07 апреля 2017

По моему опыту, в критических разделах никогда не было FIFO (возможно, команда документооборот пересекла их, заявив, что это новое в 2003 году).И да, это может привести к истощению потоков, которое мы видели много раз.Если вам нужен FIFO, вам нужен мьютекс.

Мьютексы являются объектами ядра, и поэтому их приобретение обходится дороже, чем оптимистический критический раздел на уровне кольца 3.Но FIFO не является одной из тех вещей, которые вы можете (или должны) отрицать из-за необязательности, и это не должно быть связано с «иерархией» потоков (что бы это ни было - означает ли это приоритет?),1000 нитей одинакового приоритета, ударивших по одной блокировке, легко вызовут голодание.

1 голос
/ 02 декабря 2011

Это первый раз, когда я слышу это, и когда я думаю об этом, это не кажется проблемой.

Если я правильно понял ::

OldWay:

Thread A acquired the CritSec
Thread B waiting for the CritSec , tried to acquire it at time t
Thread C waiting for the CritSec , tried to acquire it at time t + dt

When Thread A releases the CritSec, OS ensures that Thread B acquires it.

NewWay:

Thread A acquired the CritSec
Thread B waiting for the CritSec , tried to acquire it at time t
Thread C waiting for the CritSec , tried to acquire it at time t + dt

When Thread A releases the CritSec, OS may choose any Thread to acquire it. So, it may be Thread B or C that will acquire it after A releases it.

Я никогда не предполагал (и не думаю, что кто-либо еще предполагал), что нити, ожидающие CritSec, получат его в том порядке, в котором они хотели его получить.

Возможно, это возникает как проблема для некоторых профилировщиков / отладчиков или механизма мониторинга производительности, который делает это предположение ...

...