为什么线程仍然不一致?
我有一些模拟银行转账的java代码。账户类只有一个余额字段和一个向余额字段添加一些余额的转账方法。
TransferManager 定义了一个 Transfer 类,该类采用两个 Account 对象将给定金额从一个帐户转移到另一个帐户(作为参数传递)。
Manager 本身有两个重要的方法需要同步,因为它们都在同一资源上操作,并且将以线程方式调用:
public synchronized void issueTransfer(Account from, Account to, int amount) {
openTransfers.add(new Transfer(from, to, amount));
issuedTransfers++;
}
public synchronized void performTransfers() {
for(Transfer transaction : openTransfers) {
transaction.performTransfer();
performedTransfers++;
}
openTransfers.clear();
}
如果没有这里的同步语句,我会在存储和读取传输的数组列表上得到 NullPointerExceptions。
BankTest 产生 10 个线程,每个线程发出 10 笔转账。看看 BankTest.java 就可以了。问题是并不总是发出 10*10 的转账。有时有 98 或 99:
我是否必须向 BankTest.java 添加同步?我应该怎么办?还有其他想法或建议吗?
TransferManager.java:http://pastebin.com/Je4ExhUz
BankTest .java:http://pastebin.com/cdpWhHPb
Exersice3.java: http ://pastebin.com/v7pwJ5T1
Account.java:http://pastebin.com/QYEeWy5Z
I have a some java code that simulates bank transfers. The account class simply has a balance field and a transfer method that add some balance to the balance field.
The TransferManager defines a Transfer class which takes two Account objects to transfer a given amount from the one account to the other that are passed as parameters.
The Manager itself has two important methods that need to be synchronized because the both operate on the same resource and they will be called in a threaded way:
public synchronized void issueTransfer(Account from, Account to, int amount) {
openTransfers.add(new Transfer(from, to, amount));
issuedTransfers++;
}
public synchronized void performTransfers() {
for(Transfer transaction : openTransfers) {
transaction.performTransfer();
performedTransfers++;
}
openTransfers.clear();
}
Without the synchronization statement here I get NullPointerExceptions on the arraylist where Transfers are stored and read.
BankTest spawns 10 threads, each issues 10 transfers. Just have a look at BankTest.java. The problem is that not always 10*10 transfers are issued. Sometimes there are 98 or 99:
Do I have to add synchronization to BankTest.java? What should I do? Any other ideas or suggestions?
TransferManager.java: http://pastebin.com/Je4ExhUz
BankTest.java: http://pastebin.com/cdpWhHPb
Exersice3.java: http://pastebin.com/v7pwJ5T1
Account.java: http://pastebin.com/QYEeWy5Z
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这并不能保证所有线程都完成,
而是将所有线程保留在列表中并对所有线程调用 join
this does not guarantee that all threads are finished
instead keep all threads in a list and call join on all of them
竞争条件?
在不同步 openTransfers.add 语句的情况下,两个线程可以同时向 openTransfers 添加一个对象列表。假设列表为空,两个线程都可以将元素添加到第一个位置(第二个线程覆盖第一个位置),然后都增加大小。这将为您提供一个大小为 2、包含 1 个对象和 1 个空指针的列表。
这只是可能发生的许多不正确的事情之一。如果 10 个线程都执行
size = size + 1
,则完成后size
可以是 1 到 10 之间的任何值。这可以解释为什么有时会出现 99 次传输。size
是 99,现在并不意味着有 99 个项目,列表中可能有 100 个元素,或者 98,或者只是 1。您确实应该尝试同步多个线程可以写入的所有内容相同的数据。但要注意不要陷入僵局。
Race conditions?
Without synchronizing the openTransfers.add statement, two threads could simultaneously add an object to the openTransfers list. Let's say the list is empty, both threads could add the element to the first position(the second thread overwriting the first) and then both increase the size. This gives you a list of size 2 with 1 object and 1 null pointer.
This is just one of the many incorrect things that could happen. If 10 threads all execute
size = size + 1
, after finishingsize
could be any value between 1 and 10. That might explain why there are sometimes 99 transfers. Thatsize
is 99, now does not mean there are 99 items, there could be 100 elements in the list, or 98, or just 1.You really should try to synchronize everything where multiple threads can write the same data. But be careful not to deadlock.