Есть ли мьютекс в Java? - PullRequest
       50

Есть ли мьютекс в Java?

104 голосов
/ 13 марта 2011

Есть ли объект Mutex в Java или способ его создания?Я спрашиваю, потому что объект Семафор, инициализированный с 1 разрешением, не помогает мне.Подумайте об этом случае:

try {
   semaphore.acquire();
   //do stuff
   semaphore.release();
} catch (Exception e) {
   semaphore.release();
}

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

Будет ли правильный путь?

try {
   semaphore.acquire();
   //do stuff
} catch (Exception e) {
   //exception stuff
} finally {
   semaphore.release();
}

Будет ли приведенный выше код гарантировать, что семафор будет двоичным?

Ответы [ 8 ]

124 голосов
/ 13 марта 2011

Любой объект в Java можно использовать как блокировку с использованием блока synchronized.Это также автоматически позаботится о снятии блокировки при возникновении исключения.

Object someObject = ...;

synchronized (someObject) {
  ...
}

Подробнее об этом можно прочитать здесь: Внутренние блокировки и синхронизация

107 голосов
/ 13 марта 2011

см. Эту страницу: http://www.oracle.com/technetwork/articles/javase/index-140767.html

У него немного другой шаблон, который (я думаю) то, что вы ищете:

try {
  mutex.acquire();
  try {
    // do something
  } finally {
    mutex.release();
  }
} catch(InterruptedException ie) {
  // ...
}

В этом случае вы звоните release() только после успешного acquire()

23 голосов
/ 20 сентября 2012
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


private final Lock _mutex = new ReentrantLock(true);

_mutex.lock();

// your protected code here

_mutex.unlock();
6 голосов
/ 03 октября 2017

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

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

private final Lock lock = new ReentrantLock(true);

И обычный шаблон проектирования:

  lock.lock();
  try {
      // do something
  } catch (Exception e) {
      // handle the exception
  } finally {
      lock.unlock();
  }

Здесь является примером в исходном коде Java, где вы можете увидеть этот шаблон в действии.

Вторичные замки имеют дополнительное преимущество поддержки справедливости.

Используйте семафоры, только если вам нужна семантика не-релиз-релиза.

5 голосов
/ 04 апреля 2015

Я думаю, вам стоит попробовать:

Во время инициализации семафора:

Semaphore semaphore = new Semaphore(1, true);

А у тебя Runnable Implementation

try 
{
   semaphore.acquire(1);
   // do stuff

} 
catch (Exception e) 
{
// Logging
}
finally
{
   semaphore.release(1);
}
1 голос
/ 01 марта 2013

Ошибка в исходном сообщении - это вызов acqu (), установленный внутри цикла try. Вот правильный подход к использованию «двоичного» семафора (Mutex):

semaphore.acquire();
try {
   //do stuff
} catch (Exception e) {
   //exception stuff
} finally {
   semaphore.release();
}
1 голос
/ 12 марта 2012

Блокировка каждого объекта мало отличается от дизайна Mutex / Semaphore. Например, нет способа правильно реализовать обход связанных узлов с снятием блокировки предыдущего узла и захватом следующего. Но с мьютексом это легко реализовать:

Node p = getHead();
if (p == null || x == null) return false;
p.lock.acquire();  // Prime loop by acquiring first lock.
// If above acquire fails due to interrupt, the method will
//   throw InterruptedException now, so there is no need for
//   further cleanup.
for (;;) {
Node nextp = null;
boolean found;
try { 
 found = x.equals(p.item); 
 if (!found) { 
   nextp = p.next; 
   if (nextp != null) { 
     try {      // Acquire next lock 
                //   while still holding current 
       nextp.lock.acquire(); 
     } 
     catch (InterruptedException ie) { 
      throw ie;    // Note that finally clause will 
                   //   execute before the throw 
     } 
   } 
 } 
}finally {     // release old lock regardless of outcome 
   p.lock.release();
} 

В настоящее время такого класса нет в java.util.concurrent, но вы можете найти реализацию Mutext здесь Mutex.java . Что касается стандартных библиотек, Semaphore предоставляет все эти функции и многое другое.

1 голос
/ 13 марта 2011

Чтобы убедиться, что Semaphore является двоичным, вам нужно просто указать количество разрешений, равное 1, при создании семафора.У Javadocs есть немного больше объяснений.

...