Hewlett Packard Enterprise应用程序Fortify On Demand包含标题为&#34的示例代码段;示例2:以下代码将始终释放锁定。"
ReentrantLock myLock = new ReentrantLock();
try {
myLock.lock();
performOperationInCriticalSection();
myLock.unlock();
}
finally {
if (myLock != null) {
myLock.unlock();
}
}
为什么try
块中的最后一行解锁时,finally
已经处理了?它真的有必要,还是仅仅是一些冗长的编码标准的一部分? if
看起来也不必要。
答案 0 :(得分:1)
该代码throws an IllegalMonitorStateException
,因为它连续两次调用unlock()
。
<强>抛出:强>
IllegalMonitorStateException
- 如果当前线程没有持有此锁
我不得不说代码不正确,我无法猜测他们想要做什么。如果在myLock = null;
块内的unlock()
之后立即有try
,它可以正常工作,但这样做仍然是草率的代码。如果unlock()
抛出异常,那么第二次调用unlock()
也会抛出另一个异常。
正确的习语是这样的,根据例如Lock
:
Lock l = ...;
l.lock();
try {
// access the resource protected by this lock
} finally {
l.unlock();
}
如果您想要非常安全,可以使用 try-with-resources 来利用close()
引发异常而{{1}引发异常的事实正在抛出块,try
异常被添加到被抑制的异常中,因此它们都不会丢失。 (在前面的示例和HP示例中,如果close()
抛出异常,则从unlock()
块抛出的异常将完全丢失。)
try
(Here's an example output using that code on Ideone.)
或者你可以写代码which try-with-resources translates to:
class Locker implements AutoCloseable {
private final Lock lock;
Locker(Lock lock) { this.lock = Objects.requireNonNull(lock);
this.lock.lock(); }
@Override public void close() { lock.unlock(); }
}
Lock lock = ...;
try (Locker locker = new Locker(lock)) {
// If both modifySharedState() and unlock()
// throw an exception, the unlock() exception
// is added to the modifySharedState()
// exception's suppressed list.
modifySharedState();
}
但这有点难以理解。
如果逻辑比Lock lock = ...;
lock.lock();
Throwable primary = null;
try {
modifySharedState();
} catch (Throwable x) {
primary = x;
throw x;
} finally {
try {
lock.unlock();
} catch (Throwable x) {
if (primary != null) {
primary.addSuppressed(x);
// primary is already "in-flight"
// so no need to throw it again
} else {
throw x;
}
}
}
复杂,例如如果你有多个锁或者unlock()
是有条件的,那么lock()...unlock()
抛出异常的会计可能是有意义的原因。