08 Classicsynchproblems
08 Classicsynchproblems
“release all” op
Lock 0/1 ? Lock Unlock No
Block till value = 0; Value = 0
-1 -2
Bounded Buffer
Classical Synchronization Problems
Producer/Consumer
r Bounded-Buffer Problem r Finite size buffer (array) in memory shared by
multiple processes/threads
(also called Producer-Consumer)
r Producer threads “produce” an item and place in in
the buffer
r Readers and Writers Problem r Consumer threads remove an item from the buffer
and “consume” it
r Why do we need synchronization?
r Dining-Philosophers Problem m Shared data = the buffer state
m Which parts of buffer are free? Which filled?
-5 -6
1
Semaphore Solution to Semaphore Solution to
Bounded-Buffer Bounded-Buffer
semaphore_t mutex; void producer (){ void consumer (){
semaphore_t full; container_t *which; container_t *which;
semaphore_t empty; wait(empty); wait(full);
wait ( mutex); wait ( mutex);
container_t {
BOOL free = TRUE;
which = findFreeBuffer (); which = findFullBuffer ();
item_t item;
which->free = FALSE; consumeItem(which->item);
}
container_t which->item = produceItem(); which->free = TRUE;
buffer[FIXED_SIZE];
signal (mutex); signal (mutex);
void initBoundedBuffer { signal (full); signal (empty);
mutex.value = 1; } }
full.value = 0;
empty.value = FIXED_SIZE •Can we do better? Lock held while produce/consume?
}
-7 -8
2
Semaphore Solution to Readers/
Remember
Writers (Fair) void reader (){
wait(incoming);
}
}
-15 -16
-17 -18
3
Cycle in Resource Allocation
Resource Allocation Graph
Graph Philosopher 1 has chopstick 1 and
wants chopstick 0
r Deadlock can be described through a
resource allocation graph Chopstick 0 Philosopher 1 Chopstick 1
-23 -24
4
Preventing Hold and Wait Preventing No Preemption
r Do not allow processes to hold a resource when r Preemption (have to love those double negative J )
requesting others r Allow system to take back resources once granted
m Make philosophers get both chopsticks at once m Make some philosopher give back a chopstick
Window’s WaitForMultipleObjects r Disadvantage: Hard to program
m
r Make processes ask for all resources they need at m System figures out how to take away CPU and memory
the beginning without breaking programmer’s illusion
m Disadvantage: May not need all resources the whole time m How do you take away access to an open file or a lock
m Can release them early but must hold until used once granted?? Would need API to notify program and
then code to deal with the removal of the resource at
r Make processes release any held resources before arbitrary points in the code
requesting more • Checkpoint and Rollback?
m Hard to program!
-25 -26
5
Banker’s Algorithm Banker’s Algorithm
r Decide whether to grant resource (loan or invest
money, give a philosopher a chopstick, allow unsigned available[R];
process to obtain a lock, …) unsigned allocation[P][R];
r Let there be P processes and R resources; Keep unsigned maximum[P][R];
track of
m Number of units of each resource available startProcess(unsigned p){
m Maximum number of units of each resource that each for (i=0; i< R; i++){
process could request
maximum[p][i] = max number of resource i
m Current allocation of each resource to each process
that process p will need at one time;
r Real bankers cannot return money to everyone at
}
once
}
m Have a reserve requirement and rely on federal gov’t to
bail them out (FDIC)
m Play odds on who will return money
m Also bankers typically loan one processes resource to
another; OS starts out owning the resources not
borrowing -31 -32
-35 -36
6
Deadlock Detection Deadlock Detection Algorithm
r If don’t want to ever deny requests when have
BOOL deadlockHasOccured(unsigned p, unsigned r)
{
resources to grant them, then deadlock may occur unsigned work[R];
unsigned canFinish[P];
//initialization
for (j=0; j< R; j++) work[j] = available[j];
BOOL request(unsigned p, unsigned r){ for (i=0; i< P; i++){
numResourcesAllocated = 0 ;
if(available[p][r] > 0){ for (j=0; j< R; j++) {
allocation[p][r]++; numResourcesAllocated += allocation[i][j];
available[r]--; }
return TRUE; if (numResourcesAllocated == 0){
canFinish [i] = TRUE; //can’t be deadlocked if no hold and
} else { wait
return FALSE; } else {
} canFinish [i] = FALSE; //don’t know if this one is
deadlocked
} }
}
.. .. ..
-37 -38
-41 -42
7
Prevention vs Avoidance vs
Real life?
Detection
r Spectrum of low resource utilization r Most used prevention technique is resource
m Prevention gives up most chances to allocate resources ordering – reasonable for programmers to attempt
m Detection always grants resource if they are available r Avoidance and Detection to expensive
when requested
r Most systems use manual detection and recovery
r Also spectrum of runtime “overhead” m My process is hung – kill process
m Prevention has very little overhead; programmer obeys
m My machine is locked up – reboot
rules and at runtime system does little
m Avoidance uses banker’s algorithm (keep max request for r Write code that deadlocks and run it on Linux and
each process and then look before leap) on Windows – what happens?
m Detection algorithm basically involves building the full
resource allocation graph
m Avoidance and detection algorithms both O(R*P2)
-43 -44
Outtakes Gridapp
r What would it be like to do deadlock
avoidance/detection for gridapp?
r For avoidance:
m Would have to declare it’s max usage each time
through the loop for a thread or max usage
would be the whole grid and get no
concurrency?
r For detection, that would be be cool
-45 -46
-47 -48
8
Dining Philosophers Dining Philosophers
void philosophersLife(int i) {
void test(int i) {
while(1){
if ( (state[(I + NUM_PHILOSOPHERS -1) %
think();
NUM_PHILOSOPHERS] != eating) && pickupChopticks();
(state[i] == hungry) &&
eat();
(state[(i + 1) % NUM_PHILOSOPHERS] != eating)) { putdownChopsicks();
state[i] = eating;
}
self[i].signal(); }
}
}
-49 -50
-53