Professional Documents
Culture Documents
Implementing Locks: How To Write Correct Concurrent Programs? No Race
Implementing Locks: How To Write Correct Concurrent Programs? No Race
1
How to implement locks? Using interrupts (1)
All require some level of hardware support n Flawed but simple:
n For multiprocessors, requires some fancy HW support (e.g., read- n this won’t work for higher-level primitives such as semaphores and
modify-write instructions) condition variables
class Lock { int value = FREE; } class Lock { int value = FREE; }
Lock::Release() { Lock::Release() {
Lock::Acquire() { Disable interrupts; Lock::Acquire() { Disable interrupts;
Disable interrupts; value = FREE; Disable interrupts; if anyone on wait queue {
while (value != FREE) { Enable interrupts; if (value == BUSY) { Take a waiting thread off wait
Enable interrupts; } Put on queue of threads waiting for lock; queue and put it at the front
Disable interrupts; Go to sleep; of the ready queue;
} // Enable interrupts ? No! } else {
value = BUSY; } else { value = FREE;
Enable interrupts; value = BUSY; }
} } Enable interrupts
Enable interrupts }
}
2
Atomic read-modify-write Locks using test&set (1)
n On a multiprocessor, interrupt disable does not provide n Flawed but simple:
Lock:
Lock:
next_ticket = fetch_and_increment(next_ticket)
my_slot = fetch_and_increment(next_slot);
while (next_ticket != now_serving); if (my_place % numProcs == 0)
fetch_and_add(next_slot, -numProcss);
Unlock: my_slot = my_slot % numProcs;
now_serving++; while (slots[my_slot] == must_wait);
slots[my_slot] = must_wait;
n Ensures fairness
Unlock:
n Still could result in a lot of bus transactions slots[(my_slot + 1) % numProcs] = has_lock;
n Can be used to build concurrent queues
3
Summary
n Many threads + sharing state = race conditions
n one thread modifying while others reading/writing
n How to solve?
n To make multiple threads behave like one safe sequential thread,
force only one thread at a time to use shared state.
n Pure load/store methods are too complex and difficult
n General solution is to use high-level primitives, e.g., locks. It lets us
bootstrap to arbitrarily sized atomic units.