Вопрос

Пожалуйста, объясните с точки зрения Linux, Windows?

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

Спасибо

Это было полезно?

Решение

Для Windows критические разделы имеют меньший вес, чем мьютексы.

Мьютексы могут совместно использоваться процессами, но всегда приводят к системному вызову ядра, что сопряжено с некоторыми накладными расходами.

Критические разделы могут использоваться только в рамках одного процесса, но имеют то преимущество, что они переключаются в режим ядра только в случае конфликта - непреднамеренные приобретения, которые должны быть обычным случаем, выполняются невероятно быстро.В случае конфликта они входят в ядро для ожидания некоторого примитива синхронизации (например, события или семафора).

Я написал краткий пример приложения, которое сравнивает время между ними двумя.В моей системе для 1 000 000 непреднамеренных приобретений и выпусков мьютекс занимает более одной секунды.Критическая секция занимает ~ 50 мс для 1 000 000 операций обработки.

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

HANDLE mutex = CreateMutex(NULL, FALSE, NULL);
CRITICAL_SECTION critSec;
InitializeCriticalSection(&critSec);

LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
LARGE_INTEGER start, end;

// Force code into memory, so we don't see any effects of paging.
EnterCriticalSection(&critSec);
LeaveCriticalSection(&critSec);
QueryPerformanceCounter(&start);
for (int i = 0; i < 1000000; i++)
{
    EnterCriticalSection(&critSec);
    LeaveCriticalSection(&critSec);
}

QueryPerformanceCounter(&end);

int totalTimeCS = (int)((end.QuadPart - start.QuadPart) * 1000 / freq.QuadPart);

// Force code into memory, so we don't see any effects of paging.
WaitForSingleObject(mutex, INFINITE);
ReleaseMutex(mutex);

QueryPerformanceCounter(&start);
for (int i = 0; i < 1000000; i++)
{
    WaitForSingleObject(mutex, INFINITE);
    ReleaseMutex(mutex);
}

QueryPerformanceCounter(&end);

int totalTime = (int)((end.QuadPart - start.QuadPart) * 1000 / freq.QuadPart);

printf("Mutex: %d CritSec: %d\n", totalTime, totalTimeCS);

Другие советы

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

A мьютекс это алгоритм (а иногда и название структуры данных), который используется для защиты критических разделов.

Семафоры и Мониторы являются распространенными реализациями мьютекса.

На практике в Windows доступно множество реализаций мьютексов.В основном они различаются вследствие своей реализации уровнем блокировки, масштабами применения, затратами и эффективностью при различных уровнях конкуренции.Видишь CLR наизнанку - Использование параллелизма для масштабируемости для получения диаграммы затрат на различные реализации мьютекса.

Доступные примитивы синхронизации.

Тот Самый lock(object) оператор реализован с использованием Monitor - видишь MSDN для справки.

В последние годы было проведено много исследований по неблокирующая синхронизация.Цель состоит в том, чтобы реализовать алгоритмы без блокировок или без ожидания.В таких алгоритмах процесс помогает другим процессам завершить их работу, чтобы процесс мог, наконец, завершить свою работу.В результате процесс может завершить свою работу, даже когда другие процессы, пытавшиеся выполнить какую-то работу, зависают.Используя блокировки, они не снимали бы свои блокировки и не препятствовали продолжению других процессов.

В дополнение к другим ответам, следующие сведения относятся к критическим разделам Windows:

  • при отсутствии разногласий получение критической секции так же просто, как InterlockedCompareExchange операция
  • в структуре критического раздела есть место для мьютекса.Изначально он нераспределен
  • если между потоками возникает конфликт из-за критической секции, мьютекс будет выделен и использован.Производительность критического раздела снизится до производительности мьютекса
  • если вы ожидаете высокой конкуренции, вы можете выделить критическую секцию, указав количество вращений.
  • если в критической секции возникает конфликт с количеством вращений, поток, пытающийся получить критическую секцию, будет вращаться (ожидание занятости) в течение такого количества циклов процессора.Это может привести к повышению производительности по сравнению со спящим режимом, поскольку количество циклов для выполнения переключения контекста на другой поток может быть намного больше, чем количество циклов, затраченных потоком-владельцем для освобождения мьютекса
  • если количество вращений истечет, мьютекс будет выделен
  • когда поток-владелец освобождает критическую секцию, требуется проверить, выделен ли мьютекс, если это так, то он установит мьютекс для освобождения ожидающего потока

В Linux, я думаю, у них есть "блокировка вращения", которая служит для той же цели, что и критическая секция с количеством вращений.

Критический раздел и мьютекс не зависят от операционной системы, их концепции многопоточности / многопроцессорности.

Критическая секция Это фрагмент кода, который должен выполняться только сам по себе в любой момент времени (например, одновременно запущено 5 потоков и функция с именем "critical_section_function", которая обновляет массив...вы же не хотите, чтобы все 5 потоков обновляли массив одновременно.Таким образом, когда программа запускает critical_section_function(), ни один из других потоков не должен запускать свою critical_section_function.

мьютекс* Мьютекс - это способ реализации кода критического раздела (думайте о нем как о токене...поток должен обладать им, чтобы запустить critical_section_code)

"Быстрая" Windows, равная критическому выбору в Linux, была бы фьютекс, что расшифровывается как быстрый мьютекс пользовательского пространства.Разница между futex и мьютексом заключается в том, что с futex ядро включается только тогда, когда требуется арбитраж, поэтому вы экономите накладные расходы на общение с ядром каждый раз, когда изменяется атомарный счетчик.Это ..может спасти значительный количество времени на согласование блокировок в некоторых приложениях.

Фьютекс также может быть общим для процессов, используя средства, которые вы бы использовали для совместного использования мьютекса.

К сожалению, фьютексы могут быть очень сложно реализовать (PDF).(обновление 2018 года, они и близко не такие страшные, как были в 2009 году).

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

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

Критический раздел - это отрезок кода, который, как гарантирует операционная система, не будет прерван.В псевдокоде это было бы похоже:

StartCriticalSection();
    DoSomethingImportant();
    DoSomeOtherImportantThing();
EndCriticalSection();

В Windows критический раздел является локальным для вашего процесса.Мьютекс может быть общим для всех процессов.По сути, критические секции стоят намного дешевле.Не могу комментировать конкретно Linux, но в некоторых системах это просто псевдонимы для одного и того же.

Просто чтобы добавить мои 2 цента, критические разделы определяются как структура, и операции над ними выполняются в контексте пользовательского режима.

ntdll!_RTL_CRITICAL_SECTION
   +0x000 DebugInfo        : Ptr32 _RTL_CRITICAL_SECTION_DEBUG
   +0x004 LockCount        : Int4B
   +0x008 RecursionCount   : Int4B
   +0x00c OwningThread     : Ptr32 Void
   +0x010 LockSemaphore    : Ptr32 Void
   +0x014 SpinCount        : Uint4B

Принимая во внимание, что мьютексы - это объекты ядра (ExMutantObjectType), созданные в каталоге объектов Windows.Операции мьютекса в основном реализованы в режиме ядра.Например, при создании мьютекса вы в конечном итоге вызываете nt!NtCreateMutant в ядре.

Отличный ответ от Майкла.Я добавил третий тест для класса mutex, представленного в C ++ 11.Результат несколько интересен и все еще подтверждает его первоначальное одобрение объектов CRITICAL_SECTION для отдельных процессов.

mutex m;
HANDLE mutex = CreateMutex(NULL, FALSE, NULL);
CRITICAL_SECTION critSec;
InitializeCriticalSection(&critSec);

LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
LARGE_INTEGER start, end;

// Force code into memory, so we don't see any effects of paging.
EnterCriticalSection(&critSec);
LeaveCriticalSection(&critSec);
QueryPerformanceCounter(&start);
for (int i = 0; i < 1000000; i++)
{
    EnterCriticalSection(&critSec);
    LeaveCriticalSection(&critSec);
}

QueryPerformanceCounter(&end);

int totalTimeCS = (int)((end.QuadPart - start.QuadPart) * 1000 / freq.QuadPart);

// Force code into memory, so we don't see any effects of paging.
WaitForSingleObject(mutex, INFINITE);
ReleaseMutex(mutex);

QueryPerformanceCounter(&start);
for (int i = 0; i < 1000000; i++)
{
    WaitForSingleObject(mutex, INFINITE);
    ReleaseMutex(mutex);
}

QueryPerformanceCounter(&end);

int totalTime = (int)((end.QuadPart - start.QuadPart) * 1000 / freq.QuadPart);

// Force code into memory, so we don't see any effects of paging.
m.lock();
m.unlock();

QueryPerformanceCounter(&start);
for (int i = 0; i < 1000000; i++)
{
    m.lock();
    m.unlock();
}

QueryPerformanceCounter(&end);

int totalTimeM = (int)((end.QuadPart - start.QuadPart) * 1000 / freq.QuadPart);


printf("C++ Mutex: %d Mutex: %d CritSec: %d\n", totalTimeM, totalTime, totalTimeCS);

Мои результаты составили 217, 473 и 19 (обратите внимание, что мое соотношение времени для последних двух примерно сопоставимо с показателями Майкла, но моя машина по крайней мере на четыре года моложе его, так что вы можете видеть свидетельства увеличения скорости между 2009 и 2013 годами, когда вышел XPS-8700).Новый класс mutex в два раза быстрее, чем Windows mutex, но все же менее чем на одну десятую быстрее объекта Windows CRITICAL_SECTION.Обратите внимание, что я тестировал только нерекурсивный мьютекс.Объекты CRITICAL_SECTION рекурсивны (один поток может вводить их повторно при условии, что он покидает их одинаковое количество раз).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top