Java中有互斥锁吗?

在Java中是否有一个互斥对象或创build一个? 我问,因为一个信号量对象初始化1许可证不帮助我。 想想这个案例:

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

如果在第一次获取时发生exception,catch块中的释放将增加许可证,而信号量不再是二进制信号量。

请问正确的方法是?

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

上面的代码是否确保信号量是二进制的?

请参阅此页: http : //www.oracle.com/technetwork/articles/javase/index-140767.html

它有一个稍微不同的模式,这是(我认为)你在找什么:

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

在这个用法中,你只是在成功acquire()后调用release() acquire()

Java中的任何对象都可以用作使用synchronized块的锁。 当发生exception时,这也会自动解除locking。

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

为了确保一个Semaphore是二进制的,你只需要确保你在创build信号量时将许可证的数量作为1传入。 Javadocs有更多的解释。

原始文章中的错误是在try循环中的acquire()调用集。 这是一个正确的方法来使用“二进制”信号量(互斥):

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

每个对象的锁与互斥/信号量devise有一点不同。 例如,无法正确实现遍历链接节点,释放前一个节点的locking并捕获下一个节点。 但是互斥体很容易实现:

 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没有这样的类,但是您可以在这里findMutex实现Mutex.java 。 至于标准库,Semaphore提供了所有这些function,还有更多。

没有人明确提到这一点,但这种模式通常不适用于信号量。 原因是任何线程都可以释放一个信号量,但通常只需要最初locking 的拥有者线程 能够解锁 。 对于这个用例,在Java中,我们通常使用ReentrantLocks,它可以像这样创build:

 import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; private final Lock lock = new ReentrantLock(true); 

通常的使用devise模式是:

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

这里是一个java源代码的例子,你可以在这里看到这个模式。

再入式锁具有支持公平的额外好处。

仅当您需要非所有权释放语义时才使用信号量。