我有问题,我无法解决此问题
void Transfer(Account a, Account b, decimal amount)
{
lock (a) {
lock (b) {
if (a.Balance < amount)
throw new InsufficientFundsExc();
a.Balance -= amount;
b.Balance += amount;
}
}
}
问题是“这是银行账户之间的转移。”锁定(...)“结构用于对抗竞争条件。这个问题是什么?你提出什么解决方案?你可以帮助我吗?
答案 0 :(得分:10)
如果你在从B转移到A的同时从A转移到B,它可能会死锁,因为你没有锁定命令。
但为什么这个代码首先是多线程的呢?
您需要始终以相同的顺序获取锁。例如,通过为每个锁提供一个整数Id并始终首先锁定较低的ID。
答案 1 :(得分:4)
如果您可以订购帐户(按ID号或其他内容),您可以随时锁定具有较低ID的帐户。这将确保没有线程尝试锁定a
然后b
同时锁定a
然后b
的另一个线程,因为它们将锁定a
第一
答案 2 :(得分:3)
死锁
转移时(a,b,10.0);和转移(b,a,10.0);被同时调用 第一个电话会锁定一个 然后第二个可以在第一个锁定之前锁定b 并且都不能继续 - &gt;死锁
答案 3 :(得分:0)
正如CodeInChaos所说,你的问题可能是一个僵局。如果你不明白什么是死锁,那么我建议你阅读dining philosophers problem on Wikipedia。
本文以实际方式解释了这个问题,并提出了一些解决方案,包括使用locking order。
编辑:
为了进一步将您的问题与文章联系起来,银行账户是分叉(即只能专门使用的共享资源,因此需要锁定),访问代码的线程是哲学家(即不时需要使用的实体)可锁定的资源)。
答案 4 :(得分:0)
@RatchetFreak打了他的回应,为什么会发生这种情况。我认为你遇到的一个主要问题是锁是一个非常低级的构造,这使得很难想到线程方案的合理性。
我建议(如果可能的话)使用一组略高级别的结构,让自己的生活更轻松。 Daniel Chamber's在his library中具有很好的轻量级实用程序。
答案 5 :(得分:0)
想象一下,两个非常顽固的女士和丈夫一起去度假屋。他们第二天早上醒来,发现男人们走了。唯一剩下的衣服:裙子和衬衫(似乎其中一个男人喜欢穿女式服装 - 可以解释很多)。女士们意识到需要去买东西 - 食物,衣服,新婚夫妇。他们都认为“好吧,我会把衣服穿上去”,一个穿上裙子而另一个穿上衬衫。他们看到发生了什么,但每个人都太顽固了,无法改变他们的计划(并且太害羞而不能半裸出去)。他们的顽固性类似于一个愚蠢的计算机,遵循一个“当时看起来很好”的程序。他们不能/不会自动修改他们在遇到“运行时错误”时看似明智的方法,因此他们注定要饿死。那是一个死锁:等待你无法获得的资源,因为有人在等你自己在做什么。
通过更多的远见和计划,他们可以找到一种策略来确保其中一人退出。例如:
等