Есть ли Mutex в Java?

Есть ли объект Mutex в java или способ его создания? Я спрашиваю, потому что объект Semaphore, инициализированный с 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();
}

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

Ответ 1

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

У этого есть немного другой образец, который (я думаю), что вы ищете:

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

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

Ответ 2

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

Object someObject = ...;

synchronized (someObject) {
  ...
}

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

Ответ 3

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();

Ответ 4

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

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

Semaphore semaphore = new Semaphore(1, true);

И в вашем Runnable Implementation

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

} 
catch (Exception e) 
{
// Logging
}
finally
{
   semaphore.release(1);
}

Ответ 5

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

Ответ 6

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

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 предоставляет всю эту функциональность и многое другое.

Ответ 7

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

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

Ответ 8

Никто не сказал об этом явно, но этот тип шаблона обычно не подходит для семафоров. Причина в том, что любой поток может освобождать семафор, но обычно вам нужен только поток владельца, который изначально заблокирован, чтобы иметь возможность разблокировать. Для этого случая использования в 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, где вы можете увидеть этот шаблон в действии.

Реэкрант-блокировки имеют дополнительное преимущество для обеспечения справедливости.

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

Ответ 10

Посмотрите на javadoc для java.util.concurrent.locks.AbstractQueuedSynchronizer. В нем есть пример того, как написать класс Mutex.

-dbednar