Что такое мьютекс и семафор в Java? В чем главное отличие?

Ответы:

115

Семафор можно считать, а мьютекс - только до 1.

Предположим, у вас запущен поток, который принимает клиентские соединения. Этот поток может обрабатывать 10 клиентов одновременно. Затем каждый новый клиент устанавливает семафор, пока он не достигнет 10. Когда семафор имеет 10 флагов, ваш поток не будет принимать новые соединения.

Мьютексы обычно используются для защиты. Предположим, ваши 10 клиентов могут получить доступ к нескольким частям системы. Затем вы можете защитить часть системы с помощью мьютекса, чтобы, когда к этой подсистеме подключен 1 клиент, никто другой не должен иметь доступа. Вы также можете использовать семафор для этой цели. Мьютекс - это «семафор взаимного исключения» .

Эрик
источник
4
Это не совсем так. Один и тот же поток может входить в один и тот же мьютекс более одного раза, поэтому необходимо поддерживать счетчик, чтобы гарантировать сбалансированность входов и выходов.
finnw
1
@finnw, как правило, существует два типа мьютексов: рекурсивные и нерекурсивные. Использует ли Java по умолчанию рекурсивный тип?
edA-qa mort-ora-y
2
@ edA-qa mort-ora-y, термин "Mutex" не используется в спецификации Java VM или API, поэтому я предполагаю, что он относится к монитору, встроенному в каждый объект, который также похож на объект Win32, называемый Mutex . То же самое и с файлом ReentrantLock. Все это рекурсивно. Мне неизвестны «реальные» примеры нерекурсивных мьютексов (я видел их только в учебниках), поэтому я их не рассматривал.
finnw
2
Нерекурсивные мьютексы могут быть реализованы с помощью семафора со счетчиком один. Это может быть полезно, если вы хотите предотвратить рекурсивные вызовы. Это имеет практическое применение, я лично использовал его в больших проектах для обнаружения циклов в коде инициализации (A инициализирует B, который снова пытается инициализировать A).
Александр Торстлинг
1
В стандарте C ++ 11 (C ++ 0x) мьютекс не рекурсивен. Они также предоставляют отдельный рекурсивный_mutex для тех, кому это нужно. Я знаю, что мы говорим здесь о Java, но тогда многие из нас сейчас кодируют на разных языках.
Адитья Кумар Панди
139

К сожалению, все упустили самое важное различие между семафором и мьютексом; понятие « собственность ».

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

Мьютексы также могут поддерживать наследование приоритета (что может помочь с проблемой инверсии приоритета) и рекурсию (устранение одного типа взаимоблокировки).

Также следует отметить, что существуют «двоичные» семафоры и «счетные / общие» семафоры. Семафор Java является семафором подсчета и, таким образом, позволяет ему инициализировать значение больше единицы (тогда как, как уже указывалось, мьютекс может иметь только концептуальное количество единиц). На полезность этого указывалось в других сообщениях.

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

Feabhas
источник
1
Ответ Фибхаса очень важен - мьютекс проверяет, что поток, пытающийся освободить мьютекс, фактически им владеет. У меня был этот вопрос на собеседовании, поэтому стоит попытаться запомнить его.
Эндрю Пэйт
40

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

Семафор используется для управления количеством выполняемых потоков. Будет фиксированный набор ресурсов. Счетчик ресурсов будет уменьшаться каждый раз, когда поток владеет одним и тем же. Когда счетчик семафоров достигает 0, другим потокам не разрешается получать ресурс. Потоки блокируются до тех пор, пока другие потоки не освободят ресурсы.

Короче говоря, основное различие заключается в том, сколько потоков может одновременно получать ресурс?

  • Mutex - это ОДИН.
  • Семафор - его DEFINED_COUNT, (столько же, сколько семафор)
aJ.
источник
8

Мьютекс используется для последовательного доступа к ресурсу, в то время как семафор ограничивает доступ к ресурсу до заданного числа. Вы можете думать о мьютексе как о семафоре со счетчиком доступа, равным 1. Какое бы значение вы ни установили для счетчика семафоров, потоки могут получить доступ к ресурсу до того, как этот ресурс будет заблокирован.

Джейсон Коко
источник
3

Семафор - это механизм синхронизации подсчета, мьютекс - нет.

Брайан Расмуссен
источник
3

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

Шон
источник
2

На этот вопрос есть соответствующие ответы и ссылка на официальное руководство по Java: есть ли в Java Mutex?

Воздух
источник
1

Семафор :

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

Семафоры часто используются для ограничения количества потоков, которые могут получить доступ к некоторому (физическому или логическому) ресурсу.

В Java нет встроенного Mutex API. Но это может быть реализовано как двоичный семафор.

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

При таком использовании двоичный семафор имеет свойство (в отличие от многих реализаций Lock), что «блокировка» может быть снята потоком, отличным от владельца (поскольку семафоры не имеют понятия владения) . Это может быть полезно в некоторых специализированных контекстах, таких как восстановление из тупика.

Итак, ключевые различия между семафором и мьютексом:

  1. Семафор ограничивает количество потоков для доступа к ресурсу через разрешения. Mutex позволяет только одному потоку получить доступ к ресурсу.

  2. Семафор не принадлежит ни одному потоку. Потоки могут обновлять количество разрешений, вызывая acquire()и release()методы. Мьютексы должны разблокироваться только потоком, удерживающим блокировку.

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

Равиндра бабу
источник
0

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

Теперь вы могли видеть, что мьютекс - это частный случай общего семафора.

dim8
источник
0

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

Семафор имеет два построителя:

Semaphore(int num)
Semaphore(int num, boolean come)

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

Amarildo
источник
0

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

Марвен Трабелси
источник