以下代码包含潜在的死锁,但似乎是必要的:要将数据安全地从另一个容器复制到一个容器,必须锁定这两个容器以防止在另一个线程中发生更改.
void foo::copy(const foo & rhs)
{
pMutex->lock();
rhs.pMutex->lock();
// do copy
}
Run Code Online (Sandbox Code Playgroud)
Foo有一个STL容器,"do copy"主要包括使用std :: copy.如何在不引入死锁的情况下锁定两个互斥锁?
这是涉及死锁的模拟银行数据库问题.我已经有了我认为的答案,但我很好奇这是否是一个很好的解决方案.提出的问题如下:
你如何防止以下代码中的死锁?:
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来使用监听器?那会有用吗?这似乎是一种更聪明的方法.
我也可能根本不理解这一点,所以请随意给我上学,特别是如果我的解释不准确的话.谢谢.