Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
Очередные спин-блокировки являются вариантом спин-блокировок, которые хорошо работают для сильно спорящихся блокировок. Традиционные, необработанные спин-блокировки являются лучшим выбором для блокировок с легкой конкуренцией или более короткой длительности.
Преимущества использования очередной спин-блокировки включают:
Сокращение процессорного соперничества: традиционные спинлоки могут привести к значительному соперничеству за процессорное время, когда несколько потоков пытаются получить блокировку одновременно, так как они непрерывно выполняют цикл, проверяя состояние блокировки. Это может снизить производительность системы, особенно в многопроцессорных системах. Спин-блокировки в очереди снижают воздействие этого путем организации потоков в очередь. Когда поток получает блокировку, только следующая в строке активно спинирует, ожидая получения блокировки. Это сокращает циклы ЦП, потраченные на спиннинг, особенно если блокировка удерживается в течение длительного времени.
Справедливость и избегание голода: одна из проблем с основными спин-замками заключается в отсутствии справедливости; поток может голодать и никогда не получать замок, если другие потоки постоянно получают и освобождают замок. Очередные спин-блокировки устраняют это, гарантируя, что потоки получают блокировку в порядке, в котором они пытались. Эта последовательная обработка предотвращает голодание и гарантирует, что все потоки будут обслуживаться в течение времени.
Масштабируемость. По мере увеличения числа процессоров или ядер в системе эффективность механизмов синхронизации становится критической для производительности. Очередные замки спина более масштабируемы, чем традиционные, поскольку снижают нагрузку на процессоры, минимизируя активное кручение по всем ядрам. Это особенно важно в высокопроизводительных многоядерных системах, где эффективность драйвера может напрямую повлиять на общую производительность системы.
Эффективное использование системных ресурсов: за счет уменьшения ненужного вращения процессора, очереди спин-блокировок позволяют системе эффективнее использовать свои ресурсы. Это не только повышает производительность драйвера устройства, но и оказывает положительное влияние на общую скорость реагирования системы и потребление энергии, что особенно полезно в средах с учетом питания.
Простота и надежность: Несмотря на их преимущества в снижении конфликтов и повышении справедливости, очередные спинлоки скрывают сложность от разработчика. Они предоставляют простой и надежный механизм защиты общих ресурсов без необходимости реализовать сложную логику блокировки. Эта простота снижает вероятность ошибок, связанных с неправильной обработкой блокировки, что повышает надежность драйвера.
Ниже приведен упрощенный фрагмент кода, демонстрирующий описанные операции с блокировкой очереди с использованием спин-блокировки в драйвере режима ядра Windows. В этом примере показано, как объявить и инициализировать спин-блокировку с помощью KeInitializeSpinLock, а затем захватить и освободить блокировку с использованием KeAcquireInStackQueuedSpinLock и KeReleaseInStackQueuedSpinLock соответственно.
KSPIN_LOCK SpinLock;
KLOCK_QUEUE_HANDLE LockHandle;
// Initialize the spin lock
KeInitializeSpinLock(&SpinLock);
// Assume this function is called in some kind of context where
// the below operations make sense, e.g., in a device I/O path
// Acquire the queued spin lock
KeAcquireInStackQueuedSpinLock(&SpinLock, &LockHandle);
// At this point, the current thread holds the spin lock.
// Perform thread-safe operations here.
// ...
// Release the queued spin lock
KeReleaseInStackQueuedSpinLock(&LockHandle);
Драйвер выделяет структуру KLOCK_QUEUE_HANDLE, которую передает с помощью указателя в KeAcquireInStackQueuedSpinLock. Драйвер передает ту же структуру указателем на KeReleaseInStackQueuedSpinLock при освобождении спин-блокировки.
Драйверы обычно должны выделять структуру в стеке каждый раз, когда они получают блокировку. Драйвер не должен выделять структуру как часть контекста устройства, а затем совместно использовать одну и ту же структуру из нескольких потоков.
Драйверы не должны смешивать вызовы к подпрограммам очереди спин-блокировки и обычным подпрограммам KeXxxSpinLock на одной и той же спин-блокировке.
Если драйвер уже находится на уровне IRQL = DISPATCH_LEVEL, он может вместо этого вызывать KeAcquireInStackQueuedSpinLockAtDpcLevel и KeReleaseInStackQueuedSpinLockFromDpcLevel.