Рубрики
Без рубрики

Двоичный семафор против повторного входа

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

Автор оригинала: Anshul Bansal.

1. Обзор

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

2. Что такое Двоичный Семафор?

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

Для этого он сохраняет только одно разрешение на доступ. Следовательно, двоичный семафор имеет только два состояния: одно доступное разрешение или ноль доступных разрешений .

Давайте обсудим простую реализацию двоичного семафора с использованием класса Semaphore , доступного в Java:

Semaphore binarySemaphore = new Semaphore(1);
try {
    binarySemaphore.acquire();
    assertEquals(0, binarySemaphore.availablePermits());
} catch (InterruptedException e) {
    e.printStackTrace();
} finally {
    binarySemaphore.release();
    assertEquals(1, binarySemaphore.availablePermits());
}

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

Кроме того, класс Семафор предоставляет параметр справедливость . Если установлено значение true , параметр справедливость обеспечивает порядок, в котором запрашивающие потоки получают разрешения (в зависимости от времени ожидания):

Semaphore binarySemaphore = new Semaphore(1, true);

3. Что такое Реентерабельный Замок?

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

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

Например, давайте рассмотрим простую реализацию с использованием класса ReentrantLock , доступного в Java:

ReentrantLock reentrantLock = new ReentrantLock();
try {
    reentrantLock.lock();
    assertEquals(1, reentrantLock.getHoldCount());
    assertEquals(true, reentrantLock.isLocked());
} finally {
    reentrantLock.unlock();
    assertEquals(0, reentrantLock.getHoldCount());
    assertEquals(false, reentrantLock.isLocked());
}

Здесь метод lock увеличивает количество удержаний на единицу и блокирует ресурс. Аналогично, метод unlock уменьшает количество удержаний и разблокирует ресурс, если количество удержаний равно нулю.

Когда поток повторно вводит блокировку, он должен запросить разблокировку одинаковое количество раз, чтобы освободить ресурс:

reentrantLock.lock();
reentrantLock.lock();
assertEquals(2, reentrantLock.getHoldCount());
assertEquals(true, reentrantLock.isLocked());

reentrantLock.unlock();
assertEquals(1, reentrantLock.getHoldCount());
assertEquals(true, reentrantLock.isLocked());

reentrantLock.unlock();
assertEquals(0, reentrantLock.getHoldCount());
assertEquals(false, reentrantLock.isLocked());

Подобно классу Семафор , класс ReentrantLock также поддерживает параметр справедливость :

ReentrantLock reentrantLock = new ReentrantLock(true);

4. Двоичный семафор против Реентерабельный замок

4.1. Механизм

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

4.2. Право собственности

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

4.3. Природа

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

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

4.4. Гибкость

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

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

4.5. Изменение

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

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

4.6. Восстановление тупиковой ситуации

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

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

5. Заключение

В этой короткой статье мы исследовали двоичные семафорные и реентерабельные блокировки.

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

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

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

Как обычно, исходный код доступен на GitHub .