Date post: | 21-Dec-2015 |
Category: |
Documents |
View: | 220 times |
Download: | 0 times |
Outline
Summary: Synchronization Handling Deadlock
NOTE: Next topic: Memory Management, Chapters 8–9 Makeup class on Friday 3/09/07:
section §10: [email protected]:00 in ITL; [email protected]:00 in SC356 section §20: [email protected]:00 in SC342; [email protected]:00 in ITL
Exam#2 – Tues. 3/13, 7:00 pm, SC160
void startRead(){ if ( busy || (waitingWriters > 0) ) { waitingReader++; OKtoRead.wait(); waitingReaders--; } readercount = readercount + 1; OKtoRead.signal();}void endRead(){ readercount = readercount - 1; if (readercount == 0) OKtoWrite.signal();}
can a newly arriving reader enter the queue for OKtoRead? could this starve a waiting writer?
Recap: Reader/Writer Monitor
// Monitor procedures for writers:
void startWrite(){ if ( (readercount != 0) || busy ) { waitingWriters++; OKtoWrite.wait(); waitingWriters--; } busy = true;}void endWrite(){ busy = false; if (waitingReaders > 0) OKtoRead.signal(); else OKtoWrite.signal();}
Remember
Game is obtaining highest possible degree of concurrency and greatest ease of programming
Tension Simple high granularity locks easy to program Simple high granularity locks often means low
concurrency Getting more concurrency means
Finer granularity locks, more locks More complicated rules for concurrent access
Pseudo-Monitors Monitor = a lock (implied/added by compiler)
for mutual exclusion PLUS zero or more condition variables to express ordering constraints
What if we wanted to have monitor without programming language support? Declare locks and then associate condition
variables with a lock If wait on the condition variable, then release the
lock Java – “synchronized” methods
Example: Pseudo-monitorspthread_mutex_t monitorLock;
pthread_cond_t conditionVar;
void pseudoMonitorProc(void)
{
pthread_mutex_lock(&mutexLock);
…..
pthread_cond_wait(&conditionVar, &monitorLock);
….
pthread_mutex_unlock(&mutexLock);
}
Synchronization Mechanisms Hardware Solutions
disable/enable interrupts uninterruptible machine instruction (e.g. test-and-set, swap)
Software Solutions Peterson’s solution and variations semaphores:
counting & binary semaphores spinlock semaphores
monitors condition variables
Thread packages: mutex (lock), condition variables, reader-writer locks
Events, Message Passing, Timers, Regions, and others…
(busy waiting)
(busy waiting)
(busy waiting)(blocking)
(blocks other threads from running)
(blocking)
(blocking)
Software Synchronization Primitives Summary Locks
Simple semantics, often close to HW primitives Can be inefficient if implemented as a spin lock
Semaphores Internal queue – more efficient if integrated with scheduler
Monitors Language constructs that automate the locking Easy to program with where supported and where model fits
the task Once add in condition variables much of complexity is back
Events/Messages Simple model of synchronization via data sent over a channel
Value Queue “acquire”
op
“release”
op
“broadcast” or “release all” op
Lock0/1 ?
Lock
Block till value = 0; set value = 1
Unlock
value = 0 No
Semaphoreint Y
Wait, down, P
value—
If value < 0
add self to queue
Signal, up, V
value++
If value <= 0
wake up one
No?
while (getValue()<0) {
signal()
}
Condition variable N/A Y
Wait
Put self on queue
Signal
If process on queue, wake up exactly one
Easy to support
a signal all
MonitorN/A Y
Call proc in monitor
Return from proc in monitor No
Semaphores vs Monitors
If have one you can implement the other…
Converting a monitor solution to a semaphore solution
Basic concept: Each condition c; simulated with
semaphore cSem = 0; For mutual exclusion, introduce a new semaphore:
semaphore mutex = 1; A wait on a condition variable c: c.wait() becomes:
signal(mutex); // release exclusionwait(cSem); // blockwait(mutex); // regain exclusion before
accessing // shared variables What about a signal on a condition variable?
Implementing Monitors with Semaphores
semaphore_t mutex, next;int nextCount = 1;
Initialization code:mutex.value = 1;next.value = 0;
For each procedure P in Monitor,
implement P as
Wait (mutex);unsynchronizedBodyOfP();if (nextCount >0){
signal(next);}else {
signal(mutex);}
conditionVariable_t {int count;semaphore_t sem;
}condWait (conditionVariable_t *x) {
//one more waiting on this condx->count = x_count++;if (nextCount > 0){
signal(next); //wake up someone} else { signal (mutex); }wait(x->sem);x->count = x->count--;
}condSignal(conditionVariable_t *x){
//if no one waiting do nothing!if (x->count > 0){
next_count = nextCount++;signal(x->sem);wait (next);nextCount--; } }
Implementing Semaphores With Monitors Monitor semaphore {
int value;condition waitQueue;
void wait(){ value--;
while (value < 0){ //Notice Mesa semantics
condWait(&waitQueue);}
}
void signal(){value++;
condSignal(&waitQueue);
}
} //end monitor semaphore
void setValue(int value){value = newValue;
}
int getValue(){return value;
}
Need for Synchronization
Have a number of cooperating, sequential processes/threads running asynchronously. When must they synchronize?
When timing or ordering of execution is required e.g. one process/thread must wait for another
When sharing a resource Each process/thread does the following
request/acquire the resource;
use the resource;
release the resource;
resources: shared variables/files, buffers, devices (such as printers), databases, etc.
Criteria for a “good” solution Mutual exclusion is preserved The progress requirement is satisfied The bounded-waiting requirement is met.
In other words, you want the solution to be correct (under any circumstances) without any
assumptions about relative running times (no race conditions possible)
fair not subject to starvation (indefinite postponement) or
deadlock
Synchronization Mechanisms
It is common for Operating Systems to have a variety of synchronization mechanisms.
Solaris
adaptive mutexes, condition variables, semaphores, reader-writer locks, turnstiles
Windows XP dispatcher objects: mutexes, semaphores, events, timers
Linux spinlocks, semaphores, reader-writer locks, Pthread API
(mutex locks, condition variables, read-write locks)
Why??
Summary: Synchronization Synchronization primitives all boil down to
controlling access to a shared state (or resource) with a small amount of additional shared state
All need to be built on top of HW support Once have one kind, can implement the others Which one you use is a matter of matching the
primitive to the problem short-term locking: spinlocks, mutexes longer-term locking: counting semaphores, condition
variables read-only access with occasional writes: reader-writer
locks
Deadlock (aka “Deadly Embrace”)
Compliments of Oleg Dulin, CS major, Clarkson alumni
Methods for Handling Deadlock
Allow deadlock to occur, but…
Ignore it (ostrich algorithm)
Detection and recovery
Ensure that deadlock never occurs, by…
Prevention (negate at least 1 of the 4 necessary conditions for deadlock to occur)
Dynamic avoidance (be careful)
What are the consequences?
May be expensive
Constrains how requests for resources can be made
Processes must give maximum requests in advance