2017-05-07 13 views
0

Hewlett Packard EnterpriseアプリケーションFortify On Demandには、このコードスニペット「例2:次のコードは常にロックを解除します」が含まれています。このロック管理コードスニペットは不必要に複雑ですか?

ReentrantLock myLock = new ReentrantLock(); 

try { 
    myLock.lock(); 
    performOperationInCriticalSection(); 
    myLock.unlock(); 
} 
finally { 
    if (myLock != null) { 
     myLock.unlock(); 
    } 
} 

それはすでにfinallyで処理されたときにロックを解除するtryブロック内の最後の行は、そこにあるのはなぜ?それは本当に必要か、それとも冗長なコーディング標準の一部ですか? ifも不要です。

答えて

1

コード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()の会計処理

は例えば、感覚を作ることができます。

関連する問題