vis*_*oel 2 multithreading operating-system deadlock
无法理解以下摘自Galvin 第 9 版第 7 章死锁第 326 页的文本。
如果可以动态获取锁,则强加锁排序并不能保证防止死锁。例如,假设我们有一个在两个账户之间转移资金的功能。为了防止竞争条件,每个帐户都有一个关联的互斥锁,该锁是从 get lock() 函数获得的,如下面的程序所示:
void transaction(Account from, Account to, double amount)
{
mutex lock1, lock2;
lock1 = get lock(from);
lock2 = get lock(to);
acquire(lock1);
acquire(lock2);
withdraw(from, amount);
deposit(to, amount);
release(lock2);
release(lock1);
}
Run Code Online (Sandbox Code Playgroud)
如果两个线程同时调用 transaction() 函数,转换不同的帐户,则可能出现死锁。也就是说,一个线程可能会调用
transaction(checking account, savings account, 25);
Run Code Online (Sandbox Code Playgroud)
另一个可能会调用
transaction(savings account, checking account, 50);
Run Code Online (Sandbox Code Playgroud)
有人可以帮我理解这里的意思吗?
作者是马虎。所有文本真正告诉您的是,如果您不施加严格的锁定顺序,则施加严格的锁定顺序将无济于事。
示例中的代码没有强加任何锁定顺序,因为它以参数进入的任何顺序锁定锁。想象一下如果有两个并发调用会发生什么:一个线程调用,transaction(A, B)同时另一个线程调用transaction(B, A)。这两个线程将各自尝试以彼此相反的顺序锁定相同的两个锁。这是僵局的经典秘诀。
修复示例以使其确实施加严格顺序的方法是使锁定顺序明确。
void transaction(Account from, Account to, double amount)
{
mutex lock1, lock2;
if (from.getAccountNumber() < to.getAccountNumber()) {
lock1 = from.getLock();
lock2 = to.getLock();
} else {
lock1 = to.getLock();
lock2 = from.getLock();
}
acquire(lock1);
acquire(lock2);
withdraw(from, amount);
deposit(to, amount);
release(lock2);
release(lock1);
}
Run Code Online (Sandbox Code Playgroud)