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