UNIVERSITY OF WISCONSIN-MADISON
Computer Sciences Department | ||
CS 537
Spring 2000 | A. Arpaci-Dusseau | |
Quiz #2 Solutions: Wednesday, February 16 |
Do the following code segments correctly implement a critical section? If not, list a critical section requirement that is violated (one of three) and show a sample interleaving of instructions that leads to that problem, clearly designating which teller thread is executing each stream of instructions. If the implementation is correct, you do not need to prove it, just state that it is.
class BankAccount { private boolean lock[] = {false, false}; private int balance; private int accountNumber; BankAccount(int acct) { accountNumber = acct; balance = 0; } // tellerID is either 0 or 1 public void deposit(int amount, int tellerID) { lock[tellerID] = true; while (lock[1-tellerID]); balance += amount; lock[tellerID] = false; } } |
Does not guarantee progress (i.e., may cause deadlock).
Thread 0 Thread 1 lock[0] = true; lock[1] = true; while (lock[0]); while (lock[1]); |
class BankAccount { private int turn = 0; private boolean lock[] = {false, false}; private int balance; private int accountNumber; BankAccount(int acct) { accountNumber = acct; balance = 0; } // tellerID is either 0 or 1 public void deposit(int amount, int tellerID) { lock[tellerID] = true; if (tellerID == 1) { turn = 1; while (lock[1-tellerID]); } else { /* tellerID == 2 */ while (lock[1-tellerID] && turn == 1); } balance += amount; turn = 0; lock[tellerID] = false; } } |
Does not guarantee progress (i.e., may cause deadlock).
Thread 0 Thread 1 lock[0] = true; lock[1] = true; turn = 1; while (lock[0]); while (lock[1] && turn == 1); |
class BankAccount { private int turn = 0; private boolean lock = {true, true}; private int balance; private int accountNumber; BankAccount(int acct) { accountNumber = acct; balance = 0; } // tellerID is either 0 or 1 public void deposit(int amount, int tellerID) { lock[tellerID] = true; turn = 1 - tellerID; while (lock[1-tellerID] && turn == (1 - tellerID)); balance += amount; lock[tellerID] = false; } } |
Violates the progress requirement.
Thread 0 Thread 1 lock[0] = true; turn = 1; while (lock[1] && turn == 1); /* stuck until Thread 1 executes. */Even though the example will work if Thread 1 tries to enter the critical section: lock[1] = true; turn = 0; while (lock[0] && turn == 0); while (lock[1] && turn == 1); /* continues */it depends on Thread 1 eventually trying to enter the critical section for Thread 0 to proceed. This is precisely the same problem we saw in Lecture with the simple implementation using only the turn variable. The progress of Thread 0 cannot depend on a Thread that is executing elsewhere; it can depend only on threads in the entry or exit code of critical section or in the critical section itself. |
class BankAccount { private boolean lock = false; private int balance; private int accountNumber; BankAccount(int acct) { accountNumber = acct; balance = 0; } public void deposit(int amount) { boolean key = true; do { Swap(lock, key); } while (key == true); balance += amount; lock = false; } } |
Does not guarantee bounded waiting: one process may starve
Thread 0 Thread 1 do { Swap(lock == false, key == true); --> key = false; } while (key == true); /* repeats until context-switch to T0 */ do { Swap(lock == true, key == true); --> key = true; } while (key == true); balance += amount; lock = false; /* if no context-switch to T1, will acquire lock next time too */ do { Swap(lock == false, key == true); --> key = false; } while (key == true); balance += amount; /* pattern may repeat forever */ |