簡體   English   中英

編寫在多線程Java環境中更新兩個對象的方法的最佳方法?

[英]Best ways to write a method that updates two objects in a multithreaded java environment?

假設我們有一個名為AccountService的類來管理帳戶狀態。

AccountService定義為

interface AccountService{
 public void debit(account);
 public void credit(account);
 public void transfer(Account account, Account account1);

}

鑒於此定義,實現transfer()的最佳方法是什么,以便您可以保證傳輸是原子操作。

我對引用Java 1.4代碼的答案以及可能使用Java 5中的java.util.concurrent資源的答案感興趣

同步兩個Account對象並執行傳輸。 確保始終以相同的順序同步。 為此,請使Account實現Comparable ,對兩個帳戶進行排序,然后按該順序進行同步。

如果您沒有訂購帳戶,如果一個線程從A轉移到B而另一個從B轉移到A,則會出現死鎖的可能性。

這個確切的例子在Java Concurrency in Practice的第207頁討論,這是任何進行多線程Java開發的人的重要書籍。 示例代碼可從發布者的網站獲得

您可能需要獲得完整的事務支持(如果它是一個真正的應用程序)。

解決方案的難度很大程度上取決於您的環境。 詳細描述您的系統,我們會盡力幫助您(什么樣的應用程序?它使用Web服務器?哪個Web服務器?什么用於存儲數據?等等)

如果您可以保證所有訪問都是通過傳輸方法進行的,那么最簡單的方法可能就是使傳輸成為同步方法。 這將是線程安全的,因為這可以保證在任何時候只有一個線程將運行傳輸方法。

如果其他方法也可以訪問AccountService,那么您可能決定讓它們都使用單個全局鎖。 一種簡單的方法是在同步(X){...}塊中包圍訪問AccountService的所有代碼,其中X是一些共享/單一對象實例(可能是AccountService實例本身)。 這將是線程安全的,因為任何時候只有一個線程將訪問AccountService,即使它們使用不同的方法。

如果仍然不夠,那么您將需要使用更復雜的鎖定方法。 一種常見的方法是在修改帳戶之前單獨鎖定帳戶...但是您必須非常小心地以一致的順序(例如通過帳戶ID)獲取鎖定,否則您將遇到死鎖。

最后,如果AccountService是一個遠程服務,那么你進入分布式鎖定領域....除非你擁有計算機科學博士學位和多年的研究預算,你應該避免去那里。

難道你不能避免使用AtomicReference<Double>同步帳戶余額,以及get()set()嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM