繁体   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