Спинлок против семафора

каковы основные различия между семафором и spin-lock?

когда мы будем использовать семафор над спин-замком?

10 ответов


Spinlock и семафор отличаются в основном четырьмя вещами:

1. Какие они
А spinlock является одной из возможных реализаций блокировки, а именно той, которая реализуется путем напряженного ожидания ("вращение"). Семафор-это обобщение замка (или, наоборот, замок-это частный случай семафора). Как правило, но не обязательно, spinlocks действительны только в пределах одного процесса, тогда как семафоры могут использоваться для синхронизации между различными процессами, тоже.

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

насколько можно считать блокировку частным случаем семафора с максимальным значением 1.

2. Что они делают!--5-->
Как указано выше, spinlock-это замок, и поэтому механизм взаимного исключения (строго 1 к 1). Он работает путем многократного запроса и / или изменения местоположения памяти, обычно атомарным способом. Это означает, что получение spinlock является" занятой " операцией, которая, возможно, сжигает циклы процессора в течение длительного времени (может быть, навсегда!) в то время как он эффективно достигает "ничего".
Основным стимулом для такого подхода является тот факт, что контекстный переключатель имеет накладные расходы, эквивалентные вращению несколько сотен (или, возможно, тысяч) раз, поэтому, если замок может быть получен путем сжигания нескольких циклов вращения, это может быть в целом более эффективным. Кроме того, для приложений реального времени может быть неприемлемо блокировать и ждать планировщика, чтобы вернуться к ним в какое-то далекое время в будущем.

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

3. Как они ведут себя в наличие заторов
Это распространенное заблуждение, что spinlocks или алгоритмы без блокировки "обычно быстрее", или что они полезны только для" очень коротких задач " (в идеале, ни один объект синхронизации не должен удерживаться дольше, чем абсолютно необходимо, когда-либо).
Одно важное различие заключается в том, как ведут себя различные подходы при наличии заторов.

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

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

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

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

4. Как они реализуются
Семафор в настоящее время обычно обернут sys_futex под Linux (необязательно со спин-блокировкой, которая выходит после нескольких попыток).
Такой тип блокировки обычно реализуется с помощью атомарных операций, и без использования любой операционной системы. В прошлом это означало использование либо встроенных компиляторов, либо непереносимых инструкций ассемблера. Между тем как C++11 и C11 имеют атомарные операции как часть языка, поэтому, помимо общей сложности написания доказуемо правильного кода без блокировки, теперь можно реализуйте код без блокировки полностью портативным и (почти) безболезненным способом.


очень просто, семафор-это" уступающий "объект синхронизации, spinlock-это "busywait". (есть немного больше семафоров в том, что они синхронизируют несколько потоков, в отличие от мьютекса или guard или monitor или critical section, который защищает область кода от одного потока)

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

обычно, если вы вращаетесь дольше, чем Квант потока, то вы должны использовать семафор.


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


из драйверов устройств Linux от Rubinni

В отличие от семафоров, spinlocks могут использоваться в коде, который не может спать, например, обработчики прерываний


Я не эксперт ядра, но вот несколько моментов:

даже однопроцессорная машина может использовать спин-блокировки, если при компиляции ядра включено упреждение ядра. Если упреждение ядра отключено, то spin-lock (возможно) расширяется до пустота заявление.

кроме того, когда мы пытаемся сравнить Semaphore vs Spin-lock, я считаю, что семафор относится к тому, который используется в ядре, а не к IPC (userland).

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

Раман Chalotra.


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

Семафор является объектом, поставляемым операционными системами для IPC, поэтому его основное назначение-межпроцессная связь. Будучи средством, поставляемым операционной системой, его производительность не будет такой же хорошей, как у spinlock для блокировки inter-thead (хотя это возможно). Семафоры лучше фиксировать в течение более длительного времени.

это сказал-реализация splinlocks в сборке сложно, и не портативный.


Я хотел бы добавить свои наблюдения, более общие и не очень специфичные для Linux.

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

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

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

  • приобрести спин-замок (занят ожидание)
  • попробуйте семафора
  • освобождение спин-блокировки
  • если семафор не был успешно приобретен, приостановите текущий поток до тех пор, пока семафор не будет выпущен; в противном случае продолжайте критический раздел

выпуск семафора должен быть реализован следующим образом:

  • приобрести spin-lock
  • освободить семафор
  • релиз spin-lock

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

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


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

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


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

пример: в модуле драйвера устройства драйвер записывает " 0 " в аппаратном регистре R0, и теперь ему нужно дождаться, пока этот регистр R0 станет 1. H / W читает R0 и выполняет некоторую работу и пишет " 1 " в R0. Это, как правило, быстро(в микро секунд). Теперь вращаться намного лучше, чем засыпать и прерываться H / W. конечно, пока закручивающ, условие отказа H/W нужно позаботиться!

нет абсолютно никаких причин для пользовательского приложения для Spin. Это не имеет смысла. Вы собираетесь вращаться, чтобы какое-то событие произошло, и это событие должно быть завершено другим приложением уровня пользователя, которое никогда не гарантируется в течение быстрого периода времени. Итак, я не буду вращаться вообще в пользовательском режиме. Я лучше спать () или mutexlock () или semaphore lock () в пользовательском режиме.


С в чем разница между спин-блокировок и семафоров? by Мачей Piechotka:

оба управляют ограниченным ресурсом. Сначала я опишу разницу между двоичным семафором (мьютексом) и spin lock.

спин-блокировки выполните занятое ожидание-т. е. он продолжает работать цикл:

while (try_acquire_resource ()); 
 ...  
release();

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

if (!try_lock()) {
    add_to_waiting_queue ();
    wait();
}
...
process *p = get_next_process_from_waiting_queue ();
p->wakeUp ();

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

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

P(resources_sem)
resource = resources.pop()
...
resources.push(resources)
V(resources_sem)

разница между семафором, мьютексом и spinlock?

блокировка в Linux