Лучше синхронизировать с семафорами или с мониторами? - PullRequest
5 голосов
/ 22 февраля 2011

лучше синхронизировать с семафорами или с мониторами?

Ответы [ 4 ]

14 голосов
/ 23 февраля 2011

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

Вот краткое руководство, которое я нашел:

Семафоры

  • Может использоваться в любом месте программы, но не должен использоваться в мониторе
  • Wait() не всегда блокирует вызывающую программу (т. Е. Когда счетчик семафоров больше нуля).
  • Signal() либо освобождает заблокированный поток, если таковой имеется, либо увеличивает счетчик семафора.
  • Если Signal() освобождает заблокированный поток, вызывающий и освобожденный поток оба продолжают.

Переменные состояния

  • Может использоваться только в мониторах
  • Wait() всегда блокирует вызывающего абонента.
  • Signal() либо освобождает заблокированный поток, если он есть, либо сигнал теряется, как если бы это никогда не происходило.
  • Если Signal() освобождает заблокированный поток, вызывающая сторона выдает монитор (тип Hoare)или продолжается (тип меза).Только один из вызывающих или освобожденных потоков может продолжить, но не оба.

Эта информация от: http://www.cs.mtu.edu/~shene/NSF-3/e-Book/MONITOR/sema-vs-monitor.html

Некоторые полезные ресурсы:

8 голосов
/ 09 мая 2012

Если вы после минимизации головной боли, предпочитают мониторы (synchronized блоки / методы) семафорам везде, где вы чувствуете реальный выбор блокирующего примитива.Игнорируйте академические разговоры о гибкости семафоров.Вы стремитесь к надежности, а не к конфигурируемости, не так ли?

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

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

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

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

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

Обратите внимание также на этот вопрос ;хотя он использует другую терминологию, лучшие ответы там понимают «мьютекс», что означает «монитор» Java.

3 голосов
/ 08 мая 2012

Для подтверждения под мониторами подразумевается старое доброе ключевое слово synchronized.

Первый вопрос: нужен ли в вашем замке счетчик?

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

J2SE 5.0статья о параллелизме дает отличный совет здесь.Мониторы ограничены, потому что:

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

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

2 голосов
/ 25 апреля 2012

Прежде всего, вы должны решить, какой JDK вы используете. Первые выпуски Java были предоставлены только для потоков. Начиная с Java Tiger (5.0), были введены новые классы для обработки параллелизма. В частности, был предоставлен полный пакет, java.util.concurrent .

По своему опыту я обнаружил, что мониторы лучше, так как они делают код более чистым. Более того, их использование делает код более понятным . Они обычно реализуются через класс, который реализует интерфейс Lock : наиболее известные реализации, предоставляемые JDK, - это класс ReentrantLock , который определяет общую блокировку, и ReentrantReadWriteLock класс, который обеспечивает определенную запись и / или чтение блокировку.

Поэтому блокировка используется для включения / отключения доступа к общему объекту (например, списку объектов).

A Семафор - это синхронизированный объект, используемый для координации и управления потоками (в последних JDK предусмотрено множество синхронизаторов, например Semaphore , CyclicBarrier , CountdownLatch и Exchanger классов). Например, с помощью семафора вы можете выпустить фиксированное количество токенов в свой пул потоков и таким образом решить количество операций, которые могут быть выполнены одновременно. Лично мне не нравится такой подход, поскольку использование пула потоков с фьючерсами и блокировками приводит к тому же результату более чистым и безопасным способом.

Дополнительную информацию можно найти в этой книге: " Параллелизм Java на практике " и в этом руководстве IBM: " Параллелизм в JDK 5.0 ". Еще несколько хороших примеров можно найти здесь .

...