2017-07-18 52 views
-3

我有這樣的代碼解鎖lock.tryLock與超時

Lock lock = new ReentrantLock(); 

void someMethod() { 
    try { 
     if (lock.tryLock(120, TimeUnit.SECONDS)) { 
      // do stuff 
     } else { 
      // timed out 
      throw new RuntimeException("timeout"); 
     } 
    } finally { 
     lock.unlock(); 
    } 
} 

能正常工作時,除了超時時。由於超時線程不擁有該鎖,因此引發了IllegalMonitorStateExceptionLock接口中沒有isHeldByCurrentThread。如果我不想轉換爲ReentrantLock,我不得不使用一些醜陋

... 
} finally { 
    if (lock.tryLock()) { 
     lock.unlock(); 
     lock.unlock(); // twice because tryLock is called twice 
    } 
} 

... 
} finally { 
    if (!timeout) { 
     lock.unlock(); 
    } 
} 

任何更好的選擇?由於

回答

2

只有當你獲得鎖解鎖:

if (lock.tryLock(120, TimeUnit.SECONDS)) { 
    try { 
    // Do stuff. 
    } finally { 
    lock.unlock(); 
    } 
} 

需要注意的是:

+0

哇。我現在感到很傻:) – mzzzzb

0

try-with-resources是另一種選擇(除了Andy的回答),但Lock不是AutoCloseable

所以你可以寫一個包裝器,如解釋here in another SO questionhere那麼你可以使用try-with-resource與這個包裝器。

如果您不打算在您的應用程序的多個位置使用類似的構造,它可能不值得您付出努力。

編輯:詳細回答解決Sotirios Delimanolis的問題。

在我看來,OP想拋出一個RuntimeException如果鎖不能被獲取,並且弄不清finally塊鎖關閉,因爲如果鎖尚未通過線程保持它可能會引發IllegalMonitorStateException

使用Lock爲您提供了靈活性,以unlock那個程序員想要的任何地方(而不是在一定try塊的末尾或者在方法結束)&靈活性在​​關鍵字失蹤,但作爲每個操作的代碼片段,看起來他會立即解鎖try區塊,因此AutoCloseable有意義。

下面的代碼地址這兩個問題,

包裝類

import java.util.concurrent.TimeUnit; 
import java.util.concurrent.locks.ReentrantLock; 

public class CloseableReentrantLock extends ReentrantLock implements 
     AutoCloseable { 

    private static final long serialVersionUID = 1L; 


    public CloseableReentrantLock timedLock() throws InterruptedException{ 
     if(this.tryLock(120, TimeUnit.SECONDS)) 
      return this; 
     else 
      throw new RuntimeException("timeout"); 
    } 

    @Override 
    public void close() throws Exception { 
     this.unlock(); 

    } 

} 

客戶

try(CloseableReentrantLock lock = new CloseableReentrantLock().timedLock()) { //do stuff here
}

鎖定收購方案:不hing特別發生,close方法在try-with-resource塊被調用並且鎖定被解鎖。這是或多或少的方式​​塊的工作,但你不能用​​等待時間的選擇,但finally代碼搞亂&機會,程序員會錯過代碼unlock & finally不存在與syncronized等與Closeable的情況下包裝。

鎖無法獲得:在這種情況下,因爲資源沒有成功地與嘗試,與資源和試穿與資源本身拋出異常收購,close不會叫上這個資源所以IllegalMonitorStateException不會在那裏。 請參閱this question and accepted answer瞭解更多關於嘗試與資源本身的例外。

此示例代碼示出了它進一步,

public class TryResource implements AutoCloseable{ 


    public TryResource getResource(boolean isException) throws Exception{ 
     if (isException) throw new Exception("Exception from closeable getResource method"); 
     else return this; 
    } 

    public void doSomething() throws Exception { 
     System.out.println("In doSomething method"); 
    } 

    @Override 
    public void close() throws Exception { 
     System.out.println("In close method"); 
     throw new Exception("Exception from closeable close method"); 
    } 

} 

和客戶端,

public class TryResourceClient { 

    public static void main(String[] args) throws Exception { 
     try (TryResource resource = new TryResource().getResource(true)){ 
      resource.doSomething(); 
     } 
    } 

} 
+1

如果它不是'AutoCloseable',它是如何選擇的?即使使用包裝器,它將如何處理失敗鎖定?如果不值得努力,爲什麼要提起它? –

+0

我已經更新了答案,以更多地說明我的意思和我對OP的要求所理解的內容。在值得的努力部分,我不確定他是否會在他的應用程序中需要一次或幾千次的語法,所以如果你需要它一千次,最好不要讓你的代碼與最終塊混亂,讓解鎖完成自動在一個地方。 –

+0

我只在一個地方有這個構造,所以會堅持嵌套的try塊。但我同意這更清潔。感謝您花時間詳細說明 – mzzzzb