编写在多线程 java 环境中更新两个对象的方法的最佳方法?

发布于 2024-09-04 02:48:27 字数 374 浏览 4 评论 0原文

假设我们有一个名为 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 的资源的答案感兴趣

Suppose we have a class called AccountService that manages the state of accounts.

AccountService is defined as

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

}

Given this definition, what is the best way to implement transfer() so that you can guarantee that transfer is an atomic operation.

I'm interested in answers that reference Java 1.4 code as well as answers that might use resources from java.util.concurrent in Java 5

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

忘羡 2024-09-11 02:48:27

同步两个 Account 对象并进行传输。确保始终以相同的顺序进行同步。为此,请使 Account 实现 Comparable,对两个帐户进行排序,并按该顺序同步。

如果您不订购帐户,则如果一个线程从 A 传输到 B,而另一个线程从 B 传输到 A,则可能会出现死锁。

这个确切的示例在 Java 并发实践,对于任何进行多线程 Java 开发的人来说都是一本重要的书。示例代码可从发布者网站获取:

Synchronize on both Account objects and do the transfer. Make sure you always synchronize in the same order. In order to do so, make the Accounts implement Comparable, sort the two accounts, and synchronize in that order.

If you don't order the accounts, you run the possibility of deadlock if one thread transfers from A to B and another transfers from B to A.

This exact example is discussed on page 207 of Java Concurrency in Practice, a critical book for anybody doing multi-threaded Java development. The example code is available from the publisher's website:

遗失的美好 2024-09-11 02:48:27

您可能需要完整的事务支持(当然,如果它是真实的应用程序)。

解决方案的难度几乎取决于您的环境。详细描述您的系统,我们将尽力帮助您(什么样的应用程序?它使用网络服务器吗?哪个网络服务器?用于存储数据的是什么?等等)

You probably need to have a full transactions support (if it's a real application of course).

The difficulty of solution hardly depends on your environment. Describe your system in detail and we'll try to help you (what kind of application? does it use web-server? which web-server? what is used to store data? and so on)

夜深人未静 2024-09-11 02:48:27

如果您可以保证所有访问都是通过transfer方法进行的,那么最简单的方法可能就是使transfer成为同步方法。这将是线程安全的,因为这保证了任何时候只有一个线程运行该传输方法。

如果其他方法也可以访问 AccountService,那么您可能决定让它们全部使用单个全局锁。执行此操作的一个简单方法是将所有访问 AccountService 的代码包含在同步 (X) {...} 块中,其中 X 是某个共享/单例对象实例(可能是 AccountService 实例本身)。这将是线程安全的,因为任何时候只有一个线程访问 AccountService,即使它们使用不同的方法。

如果这仍然不够,那么您将需要使用更复杂的锁定方法。一种常见的方法是在修改帐户之前单独锁定帐户...但是您必须非常小心地以一致的顺序(例如按帐户 ID)获取锁定,否则您将遇到死锁。

最后,如果 AccountService 是一项远程服务,那么您就进入了分布式锁定领域……除非您拥有计算机科学博士学位并且需要花费多年的研究预算,否则您可能应该避免去那里。

If you can guarantee that all accesses are made through the transfer method, then probably the easiest approach is just to make transfer a synchronized method. This will be thread-safe because this guarantees that only one thread will be running the transfer method at any one time.

If other methods may also access the AccountService, then you might decide to have them all use a single global lock. An easy way of doing this is to surround all code that accesses the AccountService in a synchronized (X) {...} block where X is some shared / singleton object instance (that could be the AccountService instance itself). This will be thread safe because only one thread will be accessing the AccountService at any one time, even if they are in different methods.

If that still isn't sufficient, then you'll need to use more sophisticated locking approaches. One common approach would be to lock the accounts individually before you modify them... but then you must be very careful to take the locks in a consistent order (e.g. by account ID) otherwise you will run into deadlocks.

Finally if AccountService is a remote service then you are into distributed locking territory.... unless you have a PhD in computer science and years of research budget to burn you should probably avoid going there.

放赐 2024-09-11 02:48:27

难道您不能避免使用 AtomicReference 以及 get()set() 来同步帐户余额吗?

Couldn't you avoid having to synchronize using an AtomicReference<Double> for the account balance, along with get() and set()?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文