Сколько CRITICAL_SECTION можно создать?

Есть ли ограничение на количество критических секций, которые я могу инициализировать и использовать?

Мое приложение создает ряд (пару тысяч) объектов, которые должны быть потокобезопасными. Если у меня есть критический раздел в каждом, не будет ли это использовать слишком много ресурсов?

Я думал, что, поскольку мне нужно объявить свой собственный объект CRITICAL_SECTION, я не трачу ресурсы ядра впустую, как в случае с Win32 Mutex или Event? Но у меня есть только мучительное сомнение...?

Честно говоря, не все эти объекты, вероятно, должны быть потокобезопасными для моего приложения, но критический раздел находится в каком-то низкоуровневом базовом классе в библиотеке, и мне нужна пара тысяч их!

У меня может быть возможность изменить эту библиотеку, поэтому мне было интересно, есть ли способ лениво создать (и затем использовать с этого момента) критическую секцию только тогда, когда я обнаружу, что объект используется из потока, отличного от того, который он был создан в? Или это то, что Windows сделает для меня?


person Steve Folly    schedule 31.05.2009    source источник


Ответы (3)


Если вы внимательно прочитаете документацию по IntializeCriticalSectionWithSpinCount() , ясно, что каждый критический раздел поддерживается объектом Event, хотя API для критических разделов рассматривает их как непрозрачные структуры. Кроме того, комментарий «Windows 2000» к параметру dwSpinCount указывает, что объект события «выделяется по требованию».

Я не знаю какой-либо документации, в которой говорится, какие условия удовлетворяются «по запросу», но я подозреваю, что она не создается до тех пор, пока поток не заблокируется при входе в критическую секцию. Для критических секций со счетчиком вращения это может произойти только после того, как будет исчерпано время ожидания вращения.

Эмпирически говоря, я работал над приложением, которое, как я знаю, создало не менее 60 000 живых COM-объектов, каждый из которых синхронизируется со своим собственным CRITICAL_SECTION. Я никогда не видел ошибок, указывающих на то, что я исчерпал запас объектов ядра.

person Matthew Xavier    schedule 31.05.2009

Количество CRITICAL_SECTION структур, которые вы можете объявить, не ограничено — это просто структуры данных POD на самом низком уровне. Может быть некоторое ограничение на количество, которое вы можете инициализировать с помощью InitializeCriticalSection(). Согласно документации, это может привести к возникновению исключения STATUS_NO_MEMORY в Windows 2000/XP/Server 2003, но, по-видимому, оно гарантированно сработает в Vista. Они не занимают никаких ресурсов ядра, пока вы их не инициализируете (если они вообще их занимают).

Если вы обнаружите, что возникает исключение STATUS_NO_MEMORY, вы можете попробовать инициализировать CRITICAL_SECTION только для данного объекта, если есть шанс, что его можно будет использовать в нескольких потоках. Если вы знаете, что конкретный объект будет использоваться только с одним потоком, установите флаг, а затем пропустите все вызовы InitializeCriticalSection(), EnterCriticalSection(), LeaveCriticalSection() и DeleteCriticalSection().

person Adam Rosenfield    schedule 31.05.2009
comment
Спасибо Адам. Я также хотел установить ваш ответ как принятый, но я могу установить только один за раз, и эмпирические данные Мэтью с 60 000 COM-объектов вызвали у меня приятное теплое нечеткое чувство! - person Steve Folly; 01.06.2009
comment
@SteveFolly У меня была такая же реакция, когда я услышал, как кто-то использует 60 000 критических секций на практике. - person Ian Boyd; 01.05.2012

Afaik, большинство типов дескрипторов/ресурсов в Windows ограничены памятью или maxint, что наступит раньше. (теоретически на 64-битном максинте может произойти, я думаю).

Иногда легкомысленные тексты, которые вы найдете на эту тему, обычно имеют отношение только к Win9x, которая имеет некоторые ограничения. (всего 64k объектов ядра)

person Marco van de Voort    schedule 01.06.2009