2013-10-17 24 views
1

聲納報告以下問題:的Java聲納/ FindBugs的 - 多線程正確性

Multithreaded correctness - Method does not release lock on all 
exception paths findbugs : UL_UNRELEASED_LOCK_EXCEPTION_PATH 
This method acquires a JSR-166 (java.util.concurrent) lock, but does not release it on all exception paths out of the method. In general, the correct idiom for using a JSR-166 lock is: 



Lock l = ...; 
l.lock(); 
try { 
    // do something 
} finally { 
    l.unlock(); 
} 

在此代碼段:

public synchronized void put(T element) throws PreconditionException { 
     Precondition.notNull(element, "Nullobject is not allowed"); 
     lock.lock(); 
     try { 
      buffer[writeIndex++] = element; 
      if (writeIndex >= capacity) { 
       writeIndex = 0; 
      } 
      if (size.get() >= capacity) { 
       // buffer is full 
       readIndex++; 
       lastOverflow.set(System.currentTimeMillis()); 
       if (readIndex >= capacity) { 
        readIndex = 0; 
       } 
       return; 
      } 
      size.incrementAndGet(); 
     } finally { 
      try { 
       notEmpty.signal(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
      lock.unlock(); 
     } 
    } 

我不會得到它,原因是什麼,這是不是安全的?

回答

4

我認爲這表明,因爲如果您的代碼在行notEmpty.signal();上拋出Throwable的另一個子類(如Error),則不會釋放該鎖。

您可以爭辯說,如果出現錯誤,您的應用程序將會關閉,或者捕獲Exception是正確的代碼。我同意這一點,但正如FindBugs所說,有一些代碼路徑最終會導致該鎖沒有被釋放......並且沒有任何東西阻止開發者擴展Throwable:'(。

4

您可以添加一個finally解鎖以確保它被調用,相比之下,可能的異常路徑可能會導致您的try-catch。

此外,捕獲異常並僅記錄它,不應保留用於生產,因爲您肯定

} finally { 
      try { 
       notEmpty.signal(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
      finally { 
       lock.unlock(); 
      } 
     }