mon*_*tag 2 database multithreading deadlock semaphore
这是涉及死锁的模拟银行数据库问题.我已经有了我认为的答案,但我很好奇这是否是一个很好的解决方案.提出的问题如下:
你如何防止以下代码中的死锁?:
void transaction(Account from, Account to, double amount)
{
Semaphore lock1, lock2;
lock1 = getLock(from);
lock2 = getLock(to);
wait(lock1);
wait(lock2);
withdraw(from, amount);
deposit(to, amount);
signal(lock2);
signal(lock1);
}
Run Code Online (Sandbox Code Playgroud)
这可以变为死锁的方式是通过两个线程(或进程?)同时使用对立账户调用transaction()方法,即:
交易(储蓄,检查,1); 在线程1和
交易(检查,储蓄,2); 在线程2中.
从我糟糕的理解,我认为发生了什么以及它为何陷入僵局是因为没有遵守锁定顺序,因为两个线程都试图获得锁定(来自彼此?).
我的快速和肮脏的解决方案是将函数transaction()之外的锁移动到调用时它看起来像这样的位置:
//somewhere in main
Semaphore lock1, lock2;
lock1 = getLock(from);
lock2 = getLock(to);
wait(lock1);
wait(lock2);
transaction(checking, savings, 2);
signal(lock2);
signal(lock1);
//.....
Run Code Online (Sandbox Code Playgroud)
交易看起来像这样:
void transaction(Account from, Account to, double amount)
{
withdraw(from, amount);
deposit(to, amount);
}
Run Code Online (Sandbox Code Playgroud)
这样他们就永远无法同时执行,因为交易在技术上是关键部分.如果这是一个java程序,你是否也可以通过在函数声明中将void一词置为void来使用监听器?那会有用吗?这似乎是一种更聪明的方法.
我也可能根本不理解这一点,所以请随意给我上学,特别是如果我的解释不准确的话.谢谢.
我认为发生了什么以及它为何陷入僵局是因为没有遵守锁定顺序,因为两个线程都试图获得锁定
这里的问题就像你提到的那样一个线程:
wait(fromLock);
wait(toLock);
Run Code Online (Sandbox Code Playgroud)
而另一个人可能会:
wait(toLock);
wait(fromLock);
Run Code Online (Sandbox Code Playgroud)
这可能会导致死锁.
您需要做的是确保它们始终以相同的顺序锁定.您可以以某种方式使用帐户的ID来确定锁的顺序:
if (from.id < to.id) {
wait(fromLock)
wait(toLock)
transaction(checking, savings, 2);
signal(toLock);
signal(fromLock);
} else {
wait(toLock)
wait(FromLock)
transaction(checking, savings, 2);
signal(FromLock);
signal(toLock);
}
Run Code Online (Sandbox Code Playgroud)
我相信这将解决任何僵局.您可能还想检查from并且to是同一个实体.
| 归档时间: |
|
| 查看次数: |
1755 次 |
| 最近记录: |