Здравствуйте, Linuxoid, Вы писали:
L>Здравствуйте, Bell, Вы писали:
B>>CRITICAL_SECTION применяется для синхронизации потоков одного процесса, а Mutex может быть использован для синхронизации потоков различных процессов, однако CRITICAL_SECTION быстрее чем Mutex.
L>А за счет чего быстрее? Я считал что CRITICAL_SECTION внутри основывается на том же Мутексе.
На событии. Но работа с этим событием начинается только в случае конфликта доступа. Внутри критической секции есть счетчик блокировок. Когда поток берет критическую секцию, то он инкрементирует атомарно это счетчик. Если получиться 1, то можно смело продолжать работать. Если >1, то секция занята ещё кем-то и в этом случае нужно подождать её освобождения. Вот тут и задействуется объект-событие. Поток просто зависает на нём. При выходе из секции счетчик блокировок декрементируется, если он после декремента >0, то это значит, что кто-то завис в ожидании. При этом событие взводится и один из потоков, висящих на нём, освобождается. Разумеется, это упрощённая схема. Тем не менее, суть во всех случаях одна -- если нет столкновения двух потоков при захвате критической секции, то объекты ядра не задействуются и обработка происходит очень быстро.
У Рихтера написан вариант критической секции, пригодный для синхронизации потоков разных процессов. Очень советую разобрать его код (десятая глава).
Здравствуйте, Linuxoid, Вы писали:
L>В каких случаях что использовать?
CRITICAL_SECTION применяется для синхронизации потоков одного процесса, а Mutex может быть использован для синхронизации потоков различных процессов, однако CRITICAL_SECTION быстрее чем Mutex.
Здравствуйте, Linuxoid, Вы писали:
L>В каких случаях что использовать?
MSDN:
A critical section object is a synchronization object that provides synchronization similar to that provided by mutex objects, except that critical section objects can be used only by the threads of a single process. Like a mutex object, a critical section object can be owned by only one thread at a time, which makes it useful for protecting a shared resource from simultaneous access. There is no guarantee about the order in which threads obtain ownership of the critical section; however, Windows CE processes all threads equally.
B>CRITICAL_SECTION применяется для синхронизации потоков одного процесса, а Mutex может быть использован для синхронизации потоков различных процессов, однако CRITICAL_SECTION быстрее чем Mutex.
А за счет чего быстрее? Я считал что CRITICAL_SECTION внутри основывается на том же Мутексе.
Здравствуйте, Linuxoid, Вы писали:
L>А за счет чего быстрее? Я считал что CRITICAL_SECTION внутри основывается на том же Мутексе.
CRITICAL_SECTION — это, конечно, мутекс (по семантике), но сделан он не на объекте ядра HMUTEX.
Там (очень грубо говоря), есть цикл, который молотит interlocked переменную.
Здравствуйте, Linuxoid, Вы писали:
L>Здравствуйте, Bell, Вы писали:
B>>CRITICAL_SECTION применяется для синхронизации потоков одного процесса, а Mutex может быть использован для синхронизации потоков различных процессов, однако CRITICAL_SECTION быстрее чем Mutex.
L>А за счет чего быстрее? Я считал что CRITICAL_SECTION внутри основывается на том же Мутексе.
Да, но она сначала использует цикл спин-блокировки, что позволяет не переключаться в режим ядра.
Здравствуйте, Анатолий Широков, Вы писали:
АШ>Здравствуйте, Linuxoid, Вы писали:
L>>В каких случаях что использовать?
АШ>MSDN:
АШ>
АШ>A critical section object is a synchronization object that provides synchronization similar to that provided by mutex objects, except that critical section objects can be used only by the threads of a single process. Like a mutex object, a critical section object can be owned by only one thread at a time, which makes it useful for protecting a shared resource from simultaneous access. There is no guarantee about the order in which threads obtain ownership of the critical section; however, Windows CE processes all threads equally.
Дополнение на счет спин-блокировок:
Когда поток пытается войти в занятую Critical section, он переходит в состояние ожидания Т.е. в режим ядра (порядка 1000 CPU cycles) Это долго, за это время часто происходит так, что ресурс освобождается
Для этого Microsoft и ввело спин-блокировку. То есть При вызове EnterCriticalSection попытка войти происходит указанное количество раз, а потом уже переходит в режим ядра
Т.е. просто подождать иногда оказывается выгодней.
Слышал, что парни из микрософт любят число 4000, но могу путать что-то с чем -то
Вообще, в каждом случае это количество подбирается индивидуально
Дополнение(обобщение) ко всему вышенаписанному от старины Рихтера:
Mutex:
Performance Slow
Arbitrary wait WaitForSingleObject (hmtx, dwMilliseconds)
Can be waited on with other kernel objects Yes (use WaitForMultipleObjects or similar function)
Can be used across process boundaries Yes
Critical section:
Performance Fast
Arbitrary wait Not possible
Can be waited on with other kernel objects No
Can be used across process boundaries No
Кодт wrote:
> Здравствуйте, Linuxoid, Вы писали: > > L>А за счет чего быстрее? Я считал что CRITICAL_SECTION внутри основывается на том же Мутексе. > > CRITICAL_SECTION — это, конечно, мутекс (по семантике), но сделан он не на объекте ядра HMUTEX. > Там (очень грубо говоря), есть цикл, который молотит interlocked переменную.
Такой CRITICAL_SECTION был бы бесполезен на однопроцессорной машине. Spin locking применяется только на малтипроцессор, см. InitializeCriticalSectionAndSpinCount.
Здравствуйте, Шахтер, Вы писали:
Ш>Здравствуйте, Linuxoid, Вы писали:
L>>Здравствуйте, Bell, Вы писали:
B>>>CRITICAL_SECTION применяется для синхронизации потоков одного процесса, а Mutex может быть использован для синхронизации потоков различных процессов, однако CRITICAL_SECTION быстрее чем Mutex.
L>>А за счет чего быстрее? Я считал что CRITICAL_SECTION внутри основывается на том же Мутексе.
Ш>На событии. Но работа с этим событием начинается только в случае конфликта доступа. Внутри критической секции есть счетчик блокировок. Когда поток берет критическую секцию, то он инкрементирует атомарно это счетчик. Если получиться 1, то можно смело продолжать работать. Если >1, то секция занята ещё кем-то и в этом случае нужно подождать её освобождения. Вот тут и задействуется объект-событие. Поток просто зависает на нём. При выходе из секции счетчик блокировок декрементируется, если он после декремента >0, то это значит, что кто-то завис в ожидании. При этом событие взводится и один из потоков, висящих на нём, освобождается. Разумеется, это упрощённая схема. Тем не менее, суть во всех случаях одна -- если нет столкновения двух потоков при захвате критической секции, то объекты ядра не задействуются и обработка происходит очень быстро.
Ш>У Рихтера написан вариант критической секции, пригодный для синхронизации потоков разных процессов. Очень советую разобрать его код (десятая глава).
Отсюда вопрос: учитывает ли InitializeCriticalSection платформу, на которой используется критическая секция. Если кванты больше, то потеря производительности из-за нежелаемой смены задачи соответсвенно больше. Видимо, имеет смысл выбирать значение счетчика побольше (InitializeCriticalSectionAndSpinCount)?