Какова причина того, что «замки - это дорогая операция», которые произносят так часто? - PullRequest
12 голосов
/ 26 января 2012

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

Я только что посмотрел это PDC 2009 видео о параллелизме и параллелизме, и вот еще раз это упоминание о том, что «блокировки - дорогая операция».Теперь я встречал такую ​​фразу в различных текстах, книгах, и я слышал, как эксперты в этой области тоже говорят это.

Мне было интересно, что именно так дорого в получении блокировки (мьютекс)или семафор)?Это тот факт, что он вызывает команду LOCK# на уровне ассемблера?

Является ли тот факт, что получение блокировки требует вызова ядра в ОС?

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

Что происходит под одеялом?

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

Кто-нибудь может уточнить?

ПРИМЕЧАНИЕ: мне просто любопытно, я знаю, как работает многопоточность, и я не собираюсь делать глупую оптимизацию.

Ответы [ 5 ]

9 голосов
/ 26 января 2012

Параллелизм

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

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

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

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

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

Расходы

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

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

Смягчение

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

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

Терминология

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

4 голосов
/ 26 января 2012

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

4 голосов
/ 26 января 2012

Это тот факт, что он вызывает команду LOCK # на уровне ассемблера?

Нет, поскольку это не всегда происходит.

Является ли тот факт, что получение блокировки требует вызова ядра в ОС?

Нет, поскольку обычно это не делается.

На самом деле блокировкиочень, очень недорого.Это утверждение это дорого.Если вам нужно выбрать между блокировкой и конфликтом, в большинстве случаев блокировка является лучшим вариантом.

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

Например: скажем, у вас есть четыре потока, которые готовы к работе, A, B , C и D .Скажем, A и B соревнуются друг с другом (скажем, они манипулируют одной и той же коллекцией).И, скажем, C и D конкурируют друг с другом, но A не борется с C .Если A и B работают одновременно (состязание), блокировки приведут к тому, что один из них не будет готов к работе, планировщик затем запланирует C (или D ), и два потока будут работать без дальнейшего конфликта.(По крайней мере, до следующего переключения контекста.)

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

1 голос
/ 26 января 2012

Короткий ответ: нет, они не дорогие.

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

Фактический ответ требует уточнения:

Технический и Реализация против Проектного:

Технический: Дэвид Шварц ответпоясняет, что технически блокировки не замедляют код. То есть, если вы запускаете однопоточный код с инструкциями блокировки в нем, блокировки не замедляют работу. *

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

Дизайн: Реальный ответ заключается в том, что дизайн, который включает в себя блокировки, имеет тенденцию быть медленнее, чем проекты, которые этого не делают.Блокировки предназначены для замедления вашего кода.

Итак, если вам удастся разумно написать код, в котором блокировки никогда не используются или даже не нужны, вам абсолютно необходимо.Вот почему люди говорят, что «замки стоят дорого».Дело не в том, что оператор lock(obj) стоит дорого, а в том, что блокирование других потоков стоит дорого, и его следует выполнять только в тех ситуациях, когда вы оценили, что оно того стоит.

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

0 голосов
/ 26 января 2012

Блокировки часто являются спин-блокировками, которые заставляют поток «вращаться», не делая никакой полезной работы, когда блокировка снята.

Ничего не делать дорого, поскольку, как все знают: «время - деньги».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...