2017-05-07 103 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(); 
    } 
} 

爲什麼沒有在try塊以解除鎖定的最後一行,當它在finally已經處理?這是否真的有必要,還是僅僅是一些冗長的編碼標準的一部分? if看起來沒有必要。

回答

1

那個代碼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()是有條件的某些原因。