CS 444CS 544 Operating Systems Classic Synchronization Problems

  • Slides: 14
Download presentation
CS 444/CS 544 Operating Systems Classic Synchronization Problems 3/5/2007 Prof. Searleman jets@clarkson. edu

CS 444/CS 544 Operating Systems Classic Synchronization Problems 3/5/2007 Prof. Searleman [email protected] edu

Outline l l Setting up a Synchronization solution Classic Synchronization Problems l l l

Outline l l Setting up a Synchronization solution Classic Synchronization Problems l l l Readers/Writers Summary: Synchronization Primitives Implementing Synchronization Primitives NOTE: l Read: Chapter 7 l Makeup class to be scheduled Friday l Exam#2 – Tues. 3/13, 7: 00 pm, SC 160

Setting up a synchronization problem l l l How to use semaphores How to

Setting up a synchronization problem l l l How to use semaphores How to use a monitor How to use condition variables Shown in class

Classical Synchronization Problems l Bounded-Buffer Problem (also called Producer-Consumer) one-way communication with limited resources

Classical Synchronization Problems l Bounded-Buffer Problem (also called Producer-Consumer) one-way communication with limited resources l Dining-Philosophers Problem shared resources l Readers and Writers Problem shared database

Readers/writers l l Shared data area being accessed by multiple processes/threads Reader threads look

Readers/writers l l Shared data area being accessed by multiple processes/threads Reader threads look but don’t touch l l Writer threads touch too. l l We can allow multiple readers at a time. Why? If a writer present, no other writers and no readers. Why? Is Producer/Consumer a subset of this? l l l Producers and consumers are both writers Producer = writer type A; Consumer = writer type B; and there are no readers What might be a reader? Report current num full.

Semaphore Solution to Readers/ Writers (Reader Preference) semaphore_t mutex; semaphore_t ok. To. Write; int

Semaphore Solution to Readers/ Writers (Reader Preference) semaphore_t mutex; semaphore_t ok. To. Write; int num. Readers; void init{ mutex. value = 1; ok. To. Write. value = 1; num. Readers = 0; } void writer (){ wait(ok. To. Write); /* do writing 1 */ signal(ok. To. Write); } void reader (){ wait(mutex); num. Readers++; if (num. Readers == 1) wait(ok. To. Write); signal(mutex); /* do reading 2 */ wait(mutex); num. Readers--; if (num. Readers == 0) signal(ok. To. Write); signal (mutex); (1 could pass in pointer to write function) } (2 could pass in pointer Problem? Can we do better? Fairness to writers? to read function)

Monitor Solution to Readers/Writers l l l reader thread reason(s) to wait? how to

Monitor Solution to Readers/Writers l l l reader thread reason(s) to wait? how to implement? writer thread reason(s) to wait? how to implement? “fairness” l don’t want to starve either readers or writers

Reader/Writer Monitor monitor RW { // shared variables condition OKtoread, OKtowrite; int readercount, waiting.

Reader/Writer Monitor monitor RW { // shared variables condition OKtoread, OKtowrite; int readercount, waiting. Writers, waiting. Readers; boolean busy; // 4 monitor procedures void start. Read(); void end. Read(); void start. Write(); void end. Write(); // initialization code for shared variables readercount = 0; busy = false; waiting. Writers = waiting. Readers = 0; } // end monitor RW

Reader & Writer threads: l READER : l WRITER: repeat { RW. start. Read();

Reader & Writer threads: l READER : l WRITER: repeat { RW. start. Read(); /* read database */ RW. end. Read(); repeat { RW. start. Write(); /* update database */ RW. end. Write(); } until done;

// Monitor procedures for readers: void start. Read(){ if ( busy || (waiting. Writers

// Monitor procedures for readers: void start. Read(){ if ( busy || (waiting. Writers > 0) ) { waiting. Reader++; OKto. Read. wait(); waiting. Readers--; } readercount = readercount + 1; OKto. Read. signal(); } void end. Read(){ readercount = readercount - 1; if (readercount == 0) OKto. Write. signal(); }

// Monitor procedures for writers: void start. Write(){ if ( (readercount != 0) ||

// Monitor procedures for writers: void start. Write(){ if ( (readercount != 0) || busy ) { waiting. Writers++; OKto. Write. wait(); waiting. Writers--; } busy = true; } void end. Write(){ busy = false; if (waiting. Readers > 0) OKto. Read. signal(); else OKto. Write. signal(); }

Semaphore Solution to Readers/ Writers (Fair) semaphore_t read. Count. Mutex, incoming, next; int num.

Semaphore Solution to Readers/ Writers (Fair) semaphore_t read. Count. Mutex, incoming, next; int num. Readers; BOOL write. In. Progress, read. In. Progress; void init{ read. Count. Mutex. value = 1; incoming. value = 1; next. value = 1; num. Readers = 0; write. In. Progress = FALSE; read. In. Progress = FALSE; }

void reader (){ wait(incoming); if (!read. In. Progress) wait(next); wait(read. Count. Mutex); num. Readers++;

void reader (){ wait(incoming); if (!read. In. Progress) wait(next); wait(read. Count. Mutex); num. Readers++; read. In. Progress = TRUE; signal(read. Count. Mutex); // if next thread on incoming // is writer, will block on next signal(incoming); // do reading wait(read. Count. Mutex); num. Readers--; if (num. Readers == 0){ read. In. Progress = FALSE; if (next. value == 0){ signal (next); } } signal(read. Count. Mutex); } void writer() { wait(incoming); wait(next); write. In. Progress = TRUE; // let someone else move // on, and wait on next signal(incoming); // do writing write. In. Progress = FALSE; if (next. value == 0){ signal(next); } }

Remember l l Game is obtaining highest possible degree of concurrency and greatest ease

Remember l l Game is obtaining highest possible degree of concurrency and greatest ease of programming Tension l l l Simple high granularity locks easy to program Simple high granularity locks often means low concurrency Getting more concurrency means l l Finer granularity locks, more locks More complicated rules for concurrent access