如果可以动态获取锁,则强制锁定顺序不能保证锁死。这是什么意思?

问题描述:

无法了解从高尔文第9版第7章死锁页326如果可以动态获取锁,则强制锁定顺序不能保证锁死。这是什么意思?

堂堂一个锁定顺序并不能保证防止死锁如果锁可动态获取采取以下文字。例如,假设我们有一个在两个账户之间转移资金的功能。为了防止竞争条件,每个帐户具有从一个get锁()函数获得如在下面的程序中所示的相关联的互斥锁:

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); 
} 

死锁是可能的,如果两个线程同时调用该事务()功能,转换不同的帐户。也就是说,一个线程可能调用

transaction(checking account, savings account, 25); 

,另一个可能会调用

transaction(savings account, checking account, 50); 

任何人可以帮我了解这里的含义是什么?

作者是马虎。所有的文字真的告诉你,如果你没有施加严格的锁定顺序,施加严格的锁定顺序不会对你有所帮助。

该示例中的代码没有强加任何锁定顺序,因为它以参数进入的任何顺序锁定锁定。想象一下,如果有两个并发呼叫会发生什么情况:一个线程调用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); 
}