430 likes | 586 Views
Last Time: Locks & Semaphores. Implementing locks Test & Set Busy waiting Block waiting Semaphores Generalization of locks. This Time: More Synch Primitives. Reader-Writer Locks Monitors Condition Variables. Reader/Writers Problem. Suppose one object shared among many threads
E N D
Last Time: Locks & Semaphores • Implementing locks • Test & Set • Busy waiting • Block waiting • Semaphores • Generalization of locks
This Time: More Synch Primitives • Reader-Writer Locks • Monitors • Condition Variables
Reader/Writers Problem • Suppose one object shared among many threads • Each thread is either a reader or a writer • Readers – only read data, never modify • Writers – read & modify data • How should we control access to this object? • Which synchronization primitive? W R R W R
Single Lock thread A Lock.acquire() Read data Lock.release() • Drawbacks of this solution? thread B Lock.acquire() Modify data Lock.release() thread C Lock.acquire() Read data Lock.release() thread D Lock.acquire() Read data Lock.release() thread E Lock.acquire() Read data Lock.release() thread F Lock.acquire() Modify data Lock.release()
Readers/Writers Optimization • Single lock: safe, but limits concurrency • Only one thread at a time, but… • Safe to have simultaneous readers! • Allow only one writer at a time • Must guarantee mutual exclusion for writers • How to implement this?
Reader-Writer Locks • New synchronization operator:reader-writer lock • Multiple processes acquire reader-writer lock in reader mode • One process acquires reader-writer lock in writer mode • Can be built with standard synch primitives • E.g., semaphores
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in reader
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in reader
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in reader reader
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in reader reader
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in reader reader reader
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in reader reader reader
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in reader reader reader writer
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in reader reader writer
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in reader reader writer writer
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in reader writer writer
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in writer writer
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in writer writer
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in writer writer reader
Readers/Writers Algorithm • As long as there are no writers in critical section • Let readers in • If no readers or writers in critical section • Let one writer in writer • What happens next? writer reader reader
Starvation Problem • Two variants: • Give reader priority: No reader waits unless writer is already in • Give writer priority: Waiting writer always gets served first • Both variants may lead to starvation • First: writers may starve • Second: readers may starve • Concurrent control with “readers” and “writers”, by P. J. Courtois, F. Heymans, D. L. Parnas • Concurrent reading and writing, by Leslie Lamport, w/o mutual exclusion
Implementing Give-reader-priority • Can implement with two semaphores • “readerSemaphore”: protect number of readers • “writerSemaphore”: control scheduling of writers • Control access to a “database” • int getValue() • void setValue (int n)
Implementing Give-reader-priority class RWDatabase { private Database db; private int readers; private Semaphore readerSemaphore; private Semaphore writerSemaphore; RWDatabase() { readers = 0; readerSemaphore = new Semaphore (1); writerSemaphore = new Semaphore (1); } int read() { … } void write (int n) { … } };
Implementing Give-reader-priority void RWDatabase::write (int v) { writerSemaphore.wait(); db.setValue(v); // Write the value writerSemaphore.signal(); }; Write value
Implementing Give-reader-priority int RWDatabase::read() { int v; readerSemaphore.wait(); readers++; if (readers == 1) { // I’m first reader writerSemaphore.wait(); } readerSemaphore.signal(); v = db.getValue(); readerSemaphore.wait(); readers--; if (readers == 0) { // I’m last reader writerSemaphore.signal(); } readerSemaphore.signal(); return v; }; Add a reader Read, remove reader • Who can starve?
2-dinning-philosopher Problem • Shared resource: chopsticks • Totally 2 philosophers & 2 chopsticks Philosopher picks up chopstick in increasing order
3-dinning-philosopher Problem • Shared resource: chopsticks • Totally 3 philosophers & 3 chopsticks Philosopher picks up chopstick in increasing order
Problems withSemaphores & Locks • Much better than load/store • Still many drawbacks • Access to semaphores may be anywhere • Not structured • Not tied to data they control access to • Difficult to detect error
This Time: More Synch Primitives • Reader-Writer Locks • Monitors • Condition Variables
Monitors • Invented by C.A.R. “Tony” Hoare • Also invented quicksort, “Hoare triples” {a > 16}a = sqrt(a);{ a > 4 } • Monitor: High-level synchronization construct • Private data with public methods operating on data • All methods synchronized • Access of data inside monitor is mutual exclusive
Monitors syntax • monitor monitor-name { • // shared variable declarations • procedure P1 (…) { …. } • … • procedure Pn (…) {……} • Initialization code ( ….) { … } • … • }
Condition Variables • Another synchronisation primitive • condition x; • Two operations on a condition variable: • x.wait () – a process that invokes the operation is suspended. • x.signal () – resumes one of processes (if any) that invoked x.wait ()
Condition Variable in Linux • Wait for some condition to be true • Then do some action. • If condition not true: • Release lock temporarily • Waiting inside critical sections
Condition Variable in Linux: Syntax pthread_cond_t cond; pthread_cond_init (&cond, NULL); //initialize condition variable ... pthread_mutex_lock(&my_mutex); while(!certain_condition) pthread_cond_wait(&cond, &mutex); //wait pthread_mutex_unlock(&my_mutex); ... pthread_cond_signal(&cond); //signal
Condition Variables Example: Reader-writer Problem • A single reader and writer • Share a buffer which holds one item (an integer) • Reader: only read when there is item in buffer • Writer: only write when there is space in buffer
Condition Variable Example: Reader-writer Problem #include <pthread.h> #include <stdio.h> #include <stdio.h> int buffer_has_item = 0; int buffer; pthread_mutex_t mutex; pthread_cond_t cond; void * reader_function(void *) { while(1){ pthread_mutex_lock( &mutex ); while(buffer_has_item == 0)pthread_cond_wait(&cond, &mutex); if ( buffer_has_item == 1) { printf("reader consumes one item: %d.\n", buffer); buffer_has_item = 0; } pthread_mutex_unlock( &mutex ); } }
Condition Variable Example: Reader-writer Problem void writer_function(void) { while(1) { pthread_mutex_lock( &mutex ); if( buffer_has_item == 0 ){ buffer = rand() ; printf("writer produces one item: %d\n", buffer); buffer_has_item = 1; pthread_cond_signal(&cond); } pthread_mutex_unlock( &mutex ); } } int main() { pthread_t reader; pthread_mutex_init(&mutex, NULL); if (pthread_cond_init (&cond, NULL) == -1){ printf("Error setting up semaphore condition signal"); exit(-1); } pthread_create( &reader, NULL, reader_function, NULL); writer_function(); return 1; }
Condition Variables Example: Dining-philosophers Problem • Shared resource: chopsticks • Totally 5 philosophers & 5 chopsticks Philosopher may pick up chopsticks only when both available
Monitor Example: Dining-philosophers Problem • Shared resource: chopsticks • Totally 5 philosophers & 5 chopsticks
Monitor Example: Dining-philosophers Problem monitor DP { enum { THINKING; HUNGRY, EATING) state [5] ; condition self [5]; void pickup (int i) { state[i] = HUNGRY; test(i); if (state[i] != EATING) self [i].wait; } void putdown (int i) { state[i] = THINKING; // test left and right neighbors test((i + 4) % 5); test((i + 1) % 5); } void test (int i) { if ( (state[(i + 4) % 5] != EATING) && (state[i] == HUNGRY) && (state[(i + 1) % 5] != EATING) ) { state[i] = EATING ; self[i].signal () ; } } initialization_code() { for (int i = 0; i < 5; i++) state[i] = THINKING; } } • Philosopher: 0 … 4 • Philosopher may pick up chopsticks only when both available • Philosopher i • dp.pickup(i) • eat; • dp.putdown(i)
Summary • Multi-Reader-Writer problem • Permit concurrent reads • Implementable with semaphores • Dinning philosopher problem • Monitors • Tie data, methods with synchronization • Condition Variables • Release lock temporarily • Waiting inside critical sections