コードthrows an IllegalMonitorStateException
は、unlock()
を2回連続して呼び出します。 ReentrantLock.unlock
から
:
例外:
IllegalMonitorStateException
- 現在のスレッドがこのロック
を保持していない場合
私は、コードが正しくないことを言わなければならないでしょうし、彼らが何をしようとしているのか、私は本当に推測できません。 try
ブロックの中にunlock()
の直後にmyLock = null;
があったとしても機能しますが、それでもやっかいなコードです。 unlock()
が例外をスローすると、unlock()
の2回目の呼び出しでも例外がスローされます。
正しいイディオムは、このようなものです。 Lock
:
Lock l = ...;
l.lock();
try {
// access the resource protected by this lock
} finally {
l.unlock();
}
あなたが本当に安全になりたい場合は、あなたがclose()
が例外をスローした場合try
ブロックから例外がスローされている間、という事実を利用することのtry-と資源を使用することができ、 close()
例外が抑制された例外に追加され、どちらも失われません。 (unlock()
が例外をスローした場合、例外がtry
ブロックが完全に失われているからスローされ、前の例とHPの例の両方で。)
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;
}
}
}
これはちょっと難しいですが、ロジックはちょうどlock()...unlock()
よりも複雑である場合は、複数のロックを持っていたかunlock()
が何らかの理由で条件付きだった場合に例外をスローunlock()
の会計処理
は例えば、感覚を作ることができます。