这个简单的代码应该会产生死锁,但事实并非如此

时间:2011-10-20 11:43:18

标签: java concurrency synchronized

与问题I posted yesterday类似,我遇到了这个我无法理解的问题。代码非常简单,应该(我认为)会产生死锁。我甚至将帐号数量减少到2,以增加死锁的可能性。

代码很容易理解,但是要提供一些上下文。我有一个账户银行,我在账户之间进行大量转账。传输方法应该生成死锁。为什么不发生这种情况?

我只能认为代码运行速度太快,但似乎不太可能一直

这是整个代码: http://pastebin.com/HWJpuT38

4 个答案:

答案 0 :(得分:8)

问题出在这一行:

mAccounts = new ArrayList<Account>(Collections.nCopies(slots, new Account()));

基本上,只有一个Account对象,但很多引用它。因此,您只能锁定单个对象。

如果你创建了许多不同的Account对象,你应该能够很快看到死锁。

答案 1 :(得分:0)

您拥有“有争议”资源的唯一地方是您在fromaccount上然后在toaccount上同步的地方 - 其他一切只依赖于一个锁定。

如果你有另一个方法在toaccount然后在fromaccount上同步,你可能会导致死锁,但是正如代码当前它应该是完全正常的。

答案 2 :(得分:0)

我认为您需要在AccountTransferRunnable中为循环添加某种睡眠,否则调度程序将运行该线程直到结束,然后再启动另一个。

使用Sleep会让Scheduler有机会切换到第一个仍在运行的另一个线程,这会让你的代码有机会遇到死锁。

答案 3 :(得分:0)

mAccounts = new ArrayList<Account>(Collections.nCopies(slots, new Account()));

http://download.oracle.com/javase/1.4.2/docs/api/java/util/Collections.html#nCopies%28int,%20java.lang.Object%29

您最终得到了对同一对象的2个引用列表。

该对象一次只能被一个线程锁定。你永远不会陷入僵局。

我假设你想用2个不同的Account类实例初始化mAccounts。