2016-07-31 36 views
3

Javadoc和一些答案(Threads - Why a Lock has to be followed by try and finally)指出:java的嘗試終於解開成語

在大多數情況下,下面的語句,應使用:

Lock l = ...; 
l.lock(); 
try { 
    // access the resource protected by this lock 
} finally { 
    l.unlock(); 
} 

我看到這個成語在標準Java的例子庫。 這是我使用它的例子。 acc1和acc2字段是銀行賬戶的一個衆所周知的例子。主要制約因素是ACC的值的總和 - 它應該是0

public class Main { 
    int acc1; 
    int acc2; 

    ReadWriteLock lock = new ReentrantReadWriteLock(); 

    public int readSum() { 
     lock.readLock().lock(); 
     try { 
      return acc1 + acc2; 
     } finally { 
      lock.readLock().unlock(); 
     } 
    } 

    public void transfer() { 
     lock.writeLock().lock(); 
     try { 
      acc1--; // constraint is corrupted 
        // exception throwed here 
      acc2++; // constraint is regained 
     } finally { 
      lock.writeLock().unlock(); 
     } 
    } 
} 

我瞭解使用成語在讀的情況下:如果例外read方法其他線程拋出仍然可以讀/寫一致的資源。但是,如果在寫入方法中讀取的excteption讀取方法可能會讀取不一致的資源。

爲什麼讀取不一致的值比無限鎖等待更可取? 爲什麼Java庫作者更喜歡這種行爲?

+0

鎖提供某些形式的事務行爲(例如數據的一致視圖)。但是,它們不提供回滾功能。你需要自己實現或使用數據庫。 – jtahlborn

+0

當您的軟件運行一個商業網站,每天交易價值數百萬美元的業務時,如果您的客戶因永久懸掛而導致I/O錯誤,您的客戶將不會感到滿意。 (不要問我怎麼知道!) –

+0

PS:@ GhostCat的答案是關於羅伯特(「叔叔鮑勃」)馬丁所說的_分離問題_---的想法,如果你讓一團代碼負責解決兩個問題或更多不同的問題(例如,鎖定和錯誤處理),將來當需求改變時,它將變成維護噩夢。看看鮑勃叔叔的書:https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ –

回答

0

你在這裏混合了不同的概念。有:

  1. 鎖定和死鎖的預防,然後
  2. 另一個層面,讓我們把它稱爲「數據完整性」。

重點:這兩個基本上是正交的。事實上,你正在解決其中的一個問題並不能爲你解決另一個問題!

即使你看你自己的例子,你發現你嘗試/終於在那裏。但是那裏沒有趕上! 不惜一切代價 含義:如果拋出一些異常,那個異常仍然被拋出,並且一些捕獲器將不得不處理它。換句話說,如果你的「鎖定」代碼可能會遇到異常,那麼你有責任以最有意義的方式處理它。

而且,從「系統」的角度來看:當你獲得無限期鎖定時,遲早會降低整個系統的性能。如果你遇到過這種異常,那麼你會更頻繁地遇到它。所以,很可能你會很快用完線程/鎖;並且您的整個應用程序將受到影響。這正是可以減少分佈式基礎架構的問題 - 停止處理傳入請求的一個組件。長話短說:無限鎖定等待是你想要阻止的事情,因爲它會嚴重影響你的應用程序的功能!

最後:當然,這是關於平衡不同的要求。但是,例如:假設您的網上商店丟失了您剛剛從購物車中刪除商品的信息。是的,這對顧客來說很煩人。但比較一下:整個在線購物應用程序停止處理請求;因爲鎖定問題。哪個問題會更加傷害您的業務?

+0

我認爲這是不正確的比較。你可以發現你賬戶中的資金沒有了,或者你發現它在一段時間內被封鎖了。 – osseum

0

你可以回滾或給一些警告信息給用戶,但如果程序被阻止你什麼也不能做。

我同意你所說的data consistency。最終在沒有任何回滾操作或警告的情況下解鎖是非​​常危險的。

+0

拋出異常的線程可以給出一些警告。不管怎樣,它都沒有被阻止。 – osseum

+0

@ user3517035。如果線程發出警告但不解鎖它的鎖,它會阻塞其他線程。像這個例子:http://stackoverflow.com/a/6950124/3378204我不知道你是什麼意思的「它不被阻止」。 – Gearon

+0

在您的示例線程中,雙向RuntimeEx未被阻止。 – osseum

相關問題