那個代碼throws an IllegalMonitorStateException
,因爲它連續兩次調用unlock()
。
從ReentrantLock.unlock
:
拋出:
IllegalMonitorStateException
- 如果當前線程沒有保持此鎖
我不得不說的是,代碼是不正確的,我無法猜測他們在做什麼。如果try
塊內的unlock()
之後立即出現myLock = null;
,但它可以工作,但這樣做仍然是草率代碼。如果unlock()
引發異常,則第二次調用unlock()
也會引發另一個異常。
正確的習慣是這樣的,根據文件的例如。 Lock
:
Lock l = ...;
l.lock();
try {
// access the resource protected by this lock
} finally {
l.unlock();
}
如果你想成爲真正的安全,你可以使用試穿與資源採取的事實,如果close()
拋出一個異常,而從try
塊一個異常被拋出的優勢, close()
異常被添加到抑制異常中,因此它們都不會丟失。 (在前面的例子和HP例如,如果unlock()
拋出一個異常,被拋出的異常從try
塊完全丟失。)
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();
}
(Here's an example output using that code on Ideone.)
或者你可以編寫類似代碼which try-with-resources translates to:
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()
更復雜,例如,如果你有一個以上的鎖或unlock()
是有條件的某些原因。