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

есть ли объект мьютекса в 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 ответов


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

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

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

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


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

Object someObject = ...;

synchronized (someObject) {
  ...
}

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


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

Я думаю, вы должны попробовать с :

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

Semaphore semaphore = new Semaphore(1, true);

и в Runnable Implementation

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

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

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

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

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


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


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

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

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

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