This is a mock bank database problem involving deadlock. I already have what I think is the answer, but I'm curious if this is a good solution. The question posed is the following:
How do you prevent deadlock in the following code?:
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);
}
The way this can become deadlocked is via two threads (or processes?) calling the transaction() method at the same time with opposing accounts, i.e.:
transaction(savings, checking, 1); in thread 1 and
transaction(checking, savings, 2); in thread 2.
From my poor understanding, I think what is going on and why it is getting deadlocked is because the lock ordering is not obeyed since both threads are trying to get a lock (from each other?).
My quick and dirty solution would be to move the locks outside of the function transaction() to where it would look like this when called:
//somewhere in main
Semaphore lock1, lock2;
lock1 = getLock(from);
lock2 = getLock(to);
wait(lock1);
wait(lock2);
transaction(checking, savings, 2);
signal(lock2);
signal(lock1);
//.....
with transaction looking like this:
void transaction(Account from, Account to, double amount)
{
withdraw(from, amount);
deposit(to, amount);
}
That way they can never be executed at the same time, since transaction is technically the critical section. If this were a java program, could you also use monitors by putting the word synchronized after void in the function declaration? Would that work? That seems like a smarter way to do it.
I also may not be understanding this at all, so feel free to school me, especially if my explanations are not accurate. Thanks.