Когда следует использовать спин-замок вместо мьютекса?



Я думаю, что оба делают ту же работу,как вы решаете, какой из них использовать для синхронизации?

444   6  

6 ответов:

Теория

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

Проблема

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

Решение

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

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

Практика

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

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

резюме

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

продолжая предложение Меки, эта статья pthread мьютекс против pthread spinlock в блоге Александра Сандлера, Алекс на Linux показывает, как spinlock & mutexes может быть реализован для проверки поведения с помощью #ifdef.

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

обратите внимание, что в некоторых средах и условиях (например, при работе в windows на уровне диспетчеризации >= уровень диспетчеризации) вы не можете использовать мьютекс, а скорее spinlock. На unix-то же самое.

вот эквивалентный вопрос на сайте конкурента StackExchange unix: https://unix.stackexchange.com/questions/5107/why-are-spin-locks-good-choices-in-linux-kernel-design-instead-of-something-more

информация об отправке на windows системный: http://download.microsoft.com/download/e/b/a/eba1050f-a31d-436b-9281-92cdfeae4b45/IRQL_thread.doc

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

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

давайте сначала подумаем о блокировки.

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

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

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

в Windows использование Spinlock обновит поток до DISPATCH_LEVEL, что в некоторых случаях может быть запрещено, поэтому на этот раз нам пришлось использовать мьютекс (APC_LEVEL).

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

Это неправильно. При использовании спин-блоков в Uni-процессорных системах нет потерь циклов процессора, потому что как только процесс принимает спин блокировка, упреждение отключено, так что, как таковой, не может быть никого другого спиннинга! Это просто, что использование его не имеет никакого смысла! Следовательно, спин-блокировки в системах Uni заменяются на preempt_disable во время компиляции ядром!

Comments

    Ничего не найдено.