2013-04-04 3 views
2

Не существует ли концепции очереди в критических разделах Windows?Очередь критической секции

У меня есть следующие визуализации цикла в выделенном потоке:

while (!viewer->finish) 
{ 
    EnterCriticalSection(&viewer->lock); 
    viewer->renderer->begin(); 
    viewer->root->render(viewer->renderer); 
    viewer->renderer->end(); 
    LeaveCriticalSection(&viewer->lock); 
} 

Основной поток выполняет обработку сообщений, и, когда я обрабатывать события мыши, я пытаюсь войти в ту же критическую секцию, но по какой-то причине, он запускает поток рендеринга для еще тысячи итераций (около 10 секунд), прежде чем основной поток, наконец, войдет в критический раздел. Что вызывает это - даже если в этот раздел нет «очереди», разве это не должно быть больше 50/50 вместо 99.9/0.1, как в моем случае? Оба потока имеют приоритет 0.

И что такое хороший способ добавить такую ​​очередь? Достаточно ли простого флага, такого как bDoNotRenderAnything?

Редактировать: решение в моем случае было просто добавить объект события (вероятно, будет работать и логическая переменная), которая устанавливается каждый раз, когда обработчик сообщения нуждается в доступе к критическому разделу и сбрасывается после его использования. Средство визуализации не входит в раздел, если установлена ​​переменная/событие. Таким образом, обработчику сообщений не придется ждать более одной итерации рендеринга.

+0

Почему 'viewer-> finish' не защищен от одновременного доступа? Является ли он хотя бы неустойчивым? – UmNyobe

+0

Ваш цикл 'while' блокируется сразу после разблокировки, что не помогает. –

+0

Каковы приоритеты ваших основных и рендеринговых потоков? –

ответ

4

В более ранних версиях Windows критические разделы были гарантированы для получения первой очереди. Это больше не относится к Windows Server 2003 SP1.

От MSDN:

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

Windows Server 2003 и Windows XP: Темы, ожидающие в критическом разделе, добавляются в очередь ожидания; они разбужены и обычно приобретают критический раздел в том порядке, в котором они были добавлены в очередь. Однако, если потоки добавляются в эту очередь с достаточно высокой скоростью, производительность может быть снижена из-за времени, необходимого для пробуждения каждого ожидающего потока.

+0

Хорошо, этого я и хотел избежать, но спасибо. «Если все вызывающие потоки имеют один и тот же приоритет, то первая строка, первая из которых (FIFO) используется после того, как текущий поток покидает критический раздел.« Строка в MSDN путала меня. – riv

+0

@riv: Я искал цитату и единственное место, где я вижу, что он говорит о 'Windows Mobile 6.5'. Если ваш вопрос касается Windows Mobile, тогда вы должны это сказать. – NPE

+0

Да, это была моя ошибка, я привык к тому, что MSDN встроен в визуальную студию, и теперь, когда у меня ее нет, я просто ищу любую функцию, которая мне нужна, и не всегда замечаю необычную платформу. – riv

1

Согласно MSDN

There is no guarantee about the order in which waiting threads 
will acquire ownership of the critical section. 

, так что не уверен, в котором нити порядка будут выполняться. И если ваш довольно короткий

viewer->renderer->begin(); 
viewer->root->render(viewer->renderer); 
viewer->renderer->end(); 

последовательность удается восстановить CriticalSection более, что это может произойти.

+0

Ой, я просто понял, что смотрю Windows Mobile MSDN = ( – riv

3

Темы, ожидающие критической секции не приобретают критическую секцию на первый пришел, первый обслужен (MSDN)

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

0

Вы можете попробовать быстро исправить, используя SwitchToThread вызов в вашем цикле рендеринга (после определенного количества итераций), хотя я сомневаюсь, что это будет достаточно хорошее решение.

Смежные вопросы