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源代码的例子,你可以在这里看到这个模式。
再入式锁具有支持公平的额外好处。
仅当您需要非所有权释放语义时才使用信号量。