提问者:小点点

如果锁可以动态获取,强制锁排序并不能保证防止死锁。这是什么意思?


无法理解以下文字摘自加尔文第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);
}

如果两个线程同时调用trade()函数,转换不同的帐户,则可能出现死锁。也就是说,一个线程可能会调用

transaction(checking account, savings account, 25);

和另一个可能会援引

transaction(savings account, checking account, 50);

有人能帮我理解一下这里的意思吗?


共1个答案

匿名用户

作者很马虎。所有的文字真正告诉你的是,如果你不强制严格的锁定命令,强制严格的锁定命令对你没有帮助。

示例中的代码没有强加任何锁定顺序,因为它按照参数进入的任何顺序锁定锁。想象一下,如果有两个并发调用会发生什么:一个线程调用事务(A, B),而另一个线程同时调用事务(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);
}