Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Imposing a lock ordering does not guarantee deadlock prevention if locks can be acquired dynamically. What does it mean?

Unable to understand the following text taken from Galvin 9th edition Chapter 7 Deadlock Page 326.

Imposing a lock ordering does not guarantee deadlock prevention if locks can be acquired dynamically. For example, assume we have a function that transfers funds between two accounts. To prevent a race condition, each account has an associated mutex lock that is obtained from a get lock() function such as shown in the following program:

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

Deadlock is possible if two threads simultaneously invoke the transaction() function, transposing different accounts. That is, one thread might invoke

transaction(checking account, savings account, 25);

and another might invoke

transaction(savings account, checking account, 50);

Can anybody please help me understand the meaning here?

like image 602
vishalgoel Avatar asked Oct 26 '25 05:10

vishalgoel


1 Answers

The author is being sloppy. All the text really tells you is, imposing a strict locking order won't help you if you don't impose a strict locking order.

The code in the example does not impose any locking order because it locks the locks in whatever order the arguments come in. Imagine what could happen if there were two concurrent calls: One thread calls transaction(A, B) while at the same time, another thread calls transaction(B, A). The two threads would each attempt to lock the same two locks in the opposite order from the other. That's the classic recipe for deadlock.


The way to fix the example so that it did impose a strict order would be to make the locking order explicit.

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);
}
like image 96
Solomon Slow Avatar answered Oct 28 '25 23:10

Solomon Slow



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!