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

В чем основные отличия между семафором и спин-блокировкой?

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

Ответ 1

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

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

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

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

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

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

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

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

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

Ответ 4

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

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

Ответ 5

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

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

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

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

Раман Чалотра.

Ответ 6

Spinlock ссылается на реализацию межпоточной блокировки с помощью машинных зависимых инструкций по сборке (таких как test-and-set). Он называется спин-блокировкой, потому что поток просто ждет в цикле ( "вращается" ), многократно проверяя, пока блокировка не станет доступной (ожидание ожидания). Spinlocks используются в качестве замены мьютексов, которые являются объектами, предоставляемыми операционными системами (а не ЦП), поскольку шпиндельные блоки работают лучше, если они заблокированы в течение короткого периода времени.

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

Тем не менее - реализация splinlocks в сборке сложна, а не переносима.

Ответ 7

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

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

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

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

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

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

  • получить прямую блокировку
  • освободить семафор
  • отпустите кнопку со спин-блокировкой

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

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

Ответ 8

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

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

Ответ 9

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

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

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

Ответ 10

Из в чем разница между прямыми замками и семафорами? от Maciej Piechotka:

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

Заблокировать блокировку выполнить ожидание - т.е. он продолжает работать:

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

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

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

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

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

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

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

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

Ответ 11

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