Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1.

Slides:



Advertisements
Similar presentations
Operating Systems Semaphores II
Advertisements

1 Interprocess Communication 1. Ways of passing information 2. Guarded critical activities (e.g. updating shared data) 3. Proper sequencing in case of.
Operating Systems: Monitors 1 Monitors (C.A.R. Hoare) higher level construct than semaphores a package of grouped procedures, variables and data i.e. object.
1 Chapter 5 Concurrency: Mutual Exclusion and Synchronization Principals of Concurrency Mutual Exclusion: Hardware Support Semaphores Readers/Writers Problem.
Operating Systems: A Modern Perspective, Chapter 8 Slide 8-1 Copyright © 2004 Pearson Education, Inc.
Ch 7 B.
Ch. 7 Process Synchronization (1/2) I Background F Producer - Consumer process :  Compiler, Assembler, Loader, · · · · · · F Bounded buffer.
Silberschatz, Galvin and Gagne ©2009 Operating System Concepts – 8 th Edition, Chapter 6: Process Synchronization.
Operating Systems CMPSC 473 Mutual Exclusion Lecture 13: October 12, 2010 Instructor: Bhuvan Urgaonkar.
Classic Synchronization Problems
Chapter 5 Concurrency: Mutual Exclusion and Synchronization Operating Systems: Internals and Design Principles, 6/E William Stallings Patricia Roy Manatee.
Enforcing Mutual Exclusion, Semaphores. Four different approaches Hardware support Disable interrupts Special instructions Software-defined approaches.
Classical Problems of Concurrency
1 Last Time: Locks & Semaphores Implementing locks Test & Set Busy waiting Block waiting Semaphores Generalization of locks.
Chapter 6: Process Synchronization. Outline Background Critical-Section Problem Peterson’s Solution Synchronization Hardware Semaphores Classic Problems.
Concurrency: Mutual Exclusion, Synchronization, Deadlock, and Starvation in Representative Operating Systems.
A. Frank - P. Weisberg Operating Systems Introduction to Cooperating Processes.
Instructor: Umar KalimNUST Institute of Information Technology Operating Systems Process Synchronization.
1 Race Conditions/Mutual Exclusion Segment of code of a process where a shared resource is accessed (changing global variables, writing files etc) is called.
Semaphores Questions answered in this lecture: Why are semaphores necessary? How are semaphores used for mutual exclusion? How are semaphores used for.
CS 241 Section Week #4 (2/19/09). Topics This Section  SMP2 Review  SMP3 Forward  Semaphores  Problems  Recap of Classical Synchronization Problems.
Pthread (continue) General pthread program structure –Encapsulate parallel parts (can be almost the whole program) in functions. –Use function arguments.
CS3530 OPERATING SYSTEMS Summer 2014 Synchronization Chapter 6.
1 Processes Chapter Processes 2.3 Interprocess communication 2.4 Classical IPC problems 2.5 Scheduling.
© Janice Regan, CMPT 300, May CMPT 300 Introduction to Operating Systems Classical problems.
6.3 Peterson’s Solution The two processes share two variables: Int turn; Boolean flag[2] The variable turn indicates whose turn it is to enter the critical.
Critical Problem Revisit. Critical Sections Mutual exclusion Only one process can be in the critical section at a time Without mutual exclusion, results.
Operating Systems CMPSC 473 Mutual Exclusion Lecture 14: October 14, 2010 Instructor: Bhuvan Urgaonkar.
Copyright ©: University of Illinois CS 241 Staff1 Synchronization and Semaphores.
Thread Synchronization Tutorial #8 CPSC 261. A thread is a virtual processor Each thread is provided the illusion that it owns a core – Copy of the registers.
1 Using Semaphores CS 241 March 14, 2012 University of Illinois Slides adapted in part from material accompanying Bryant & O’Hallaron, “Computer Systems:
4061 Session 21 (4/3). Today Thread Synchronization –Condition Variables –Monitors –Read-Write Locks.
Concurrency: Mutual Exclusion and Synchronization Chapter 5.
Synchronizing Threads with Semaphores
1 Interprocess Communication (IPC) - Outline Problem: Race condition Solution: Mutual exclusion –Disabling interrupts; –Lock variables; –Strict alternation.
Operating Systems ECE344 Ashvin Goel ECE University of Toronto Synchronization.
Silberschatz, Galvin and Gagne ©2009 Operating System Concepts – 8 th Edition, Lecture 11: Synchronization (Chapter 6, cont)
1 Inter Process Communication & Timers. 2 Time.h (page R:Ch9 pp ) #include time_t time(time_t *calptr); Epoch: 00:00 (midnight), Jan 1, 1970 GMT.
1 Condition Variables CS 241 Prof. Brighten Godfrey March 16, 2012 University of Illinois.
CIS Operating Systems Synchronization Professor Qiang Zeng Fall 2015.
Semaphores Ref: William Stallings G.Anuradha. Principle of a Semaphore Two or more processes can cooperate by means of simple signals, such that a process.
CS252: Systems Programming Ninghui Li Based on Slides by Prof. Gustavo Rodriguez-Rivera Topic 13: Condition Variable, Read/Write Lock, and Deadlock.
CS 241 Section Week #7 (10/22/09). Topics This Section  Midterm Statistics  MP5 Forward  Classical Synchronization Problems  Problems.
Copyright ©: Nahrstedt, Angrave, Abdelzaher1 Synchronization.
6.1 Silberschatz, Galvin and Gagne ©2009 Operating System Concepts with Java – 8 th Edition Module 6: Process Synchronization.
ITEC 502 컴퓨터 시스템 및 실습 Chapter 3-3: Process Synchronization Mi-Jung Choi DPNM Lab. Dept. of CSE, POSTECH.
1 Processes and Threads Part II Chapter Processes 2.2 Threads 2.3 Interprocess communication 2.4 Classical IPC problems 2.5 Scheduling.
Producer-Consumer Problem David Monismith cs550 Operating Systems.
Silberschatz, Galvin and Gagne ©2013 Operating System Concepts – 9 th Edition Chapter 5: Process Synchronization.
pThread synchronization
CS 311/350/550 Semaphores. Semaphores – General Idea Allows two or more concurrent threads to coordinate through signaling/waiting Has four main operations.
Case Study: Pthread Synchronization Dr. Yingwu Zhu.
6.1 Silberschatz, Galvin and Gagne ©2005 Operating System Principles 6.5 Semaphore Less complicated than the hardware-based solutions Semaphore S – integer.
Chapter 5 Concurrency: Mutual Exclusion and Synchronization Operating Systems: Internals and Design Principles, 6/E William Stallings Patricia Roy Manatee.
Chien-Chung Shen CIS/UD
Synchronization and Semaphores
Auburn University COMP 3500 Introduction to Operating Systems Synchronization: Part 4 Classical Synchronization Problems.
CIS Operating Systems Synchronization
HW1 and Synchronization & Queuing
Ref: William Stallings,Galvin, Naresh Chauhan G.Anuradha
Chapter 5: Process Synchronization
Process Synchronization
Concurrency: Mutual Exclusion and Synchronization
Concurrency: Mutual Exclusion and Process Synchronization
CSE 451: Operating Systems Autumn Lecture 8 Semaphores and Monitors
Synchronization Primitives – Semaphore and Mutex
Chapter 6 Synchronization Principles
CSE 153 Design of Operating Systems Winter 2019
Lecture 12 CV and Semaphores
Presentation transcript:

Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1

Condition Variable Without condition variables,  Threads continually poll to check if the condition is met  Busy waiting! With condition variables  Same goal without polling Copyright ©: University of Illinois CS 241 Staff2

Inside a condition variable struct pthread_cond { int waiting; handle_t semaphore; }; Copyright ©: University of Illinois CS 241 Staff3 Number of threads waiting on the condition variable A semaphore for synchronization

Inside a condition variable int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { atomic_increment(&cond->waiting); pthread_mutex_unlock(mutex); if (wait(cond->semaphore, INFINITE) < 0) return errno; atomic_decrement(&cond->waiting); pthread_mutex_lock(mutex); return 0; } Copyright ©: University of Illinois CS 241 Staff4 pthread_mutex_lock is always called before pthread_cond_wait to acquire lock Have lock int pthread_cond_signal(pthread_cond_t *cond) { if (cond->waiting) semrel(cond->semaphore, 1); return 0; } Have lock Thread always has lock when returning from pthread_cond_wait

More Complex Example Master thread  Spawns a number of concurrent slaves  Waits until all of the slaves have finished to exit  Tracks current number of slaves executing A mutex is associated with count and a condition variable with the mutex Copyright ©: University of Illinois CS 241 Staff5

Example #include #define NO_OF_PROCS 4 typedef struct _SharedType { int count; /* number of active slaves */ pthread_mutex_t lock; /* mutex for count */ pthread_cond_t done; /* sig. by finished slave */ } SharedType, *SharedType_ptr; SharedType_ptr shared_data; Copyright ©: University of Illinois CS 241 Staff6

Example: Main main(int argc, char **argv) { int res; /* allocate shared data */ if ((sh_data = (SharedType *) malloc(sizeof(SharedType))) == NULL) { exit(1); } sh_data->count = 0; /* allocate mutex */ if ((res = pthread_mutex_init(&sh_data- >lock, NULL)) != 0) { exit(1); } /* allocate condition var */ if ((res = pthread_cond_init(&sh_data- >done, NULL)) != 0) { exit(1); } /* generate number of slaves to create */ srandom(0); /* create up to 15 slaves */ master((int) random()%16); } Copyright ©: University of Illinois CS 241 Staff7

Example: Main main(int argc, char **argv) { int res; /* allocate shared data */ if ((sh_data = (SharedType *) malloc(sizeof(SharedType))) == NULL) { exit(1); } sh_data->count = 0; /* allocate mutex */ if ((res = pthread_mutex_init(&sh_data- >lock, NULL)) != 0) { exit(1); } /* allocate condition var */ if ((res = pthread_cond_init(&sh_data- >done, NULL)) != 0) { exit(1); } /* generate number of slaves to create */ srandom(0); /* create up to 15 slaves */ master((int) random()%16); } Copyright ©: University of Illinois CS 241 Staff8 pthread_mutex_t data_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cont_t data_cond = PTHREAD_COND_INITIALIZER;

Example: Master master(int nslaves) { int i; pthread_t id; for (i = 1; i <= nslaves; i += 1) { pthread_mutex_lock(&sh_data- >lock); /* start slave and detach */ shared_data->count += 1; pthread_create(&id, NULL, (void* (*)(void *))slave, (void *)sh_data); pthread_mutex_unlock(&sh_data- >lock); } pthread_mutex_lock(&sh_data- >lock); while (sh_data->count != 0) pthread_cond_wait(&sh_data- >done, &sh_data->lock); pthread_mutex_unlock(&sh_data- >lock); printf("All %d slaves have finished.\n", nslaves); pthread_exit(0); } Copyright ©: University of Illinois CS 241 Staff9

Example: Slave void slave(void *shared) { int i, n; sh_data = shared; printf(“Slave.\n", n); n = random() % 1000; for (i = 0; i < n; i+= 1) Sleep(10); /* mutex for shared data */ pthread_mutex_lock(&sh_data- >lock); /* dec number of slaves */ sh_data->count -= 1; /* done running */ printf("Slave finished %d cycles.\n", n); /* signal that you are done working */ pthread_cond_signal(&sh_data- >done); /* release mutex for shared data */ pthread_mutex_unlock(&sh_data- >lock); } Copyright ©: University of Illinois CS 241 Staff10

Semaphores vs. CVs Semaphore Integer value (>=0) Wait does not always block Signal either releases thread or inc’s counter If signal releases thread, both threads continue afterwards Condition Variables No integer value Wait always blocks Signal either releases thread or is lost If signal releases thread, only one of them continue Copyright ©: University of Illinois CS 241 Staff11

Classical Synchronization Problems 12Copyright ©: University of Illinois CS 241 Staff

This lecture Goals  Introduce classical synchronization problems Topics  Producer-Consumer Problem  Reader-Writer Problem  Dining Philosophers Problem  Sleeping Barber’s Problem 13Copyright ©: University of Illinois CS 241 Staff

Chefs cook items and put them on a conveyer belt 14Copyright ©: University of Illinois CS 241 Staff Waiters pick items off the belt

Now imagine many chefs! 15Copyright ©: University of Illinois CS 241 Staff And many waiters!

A potential mess! 16Copyright ©: University of Illinois CS 241 Staff

Producer-Consumer Problem Producers insert items Consumers remove items Shared resource: bounded buffer  Efficient implementation: circular buffer with an insert and a removal pointer Chef = Producer Waiter= Consumer 17Copyright ©: University of Illinois CS 241 Staff

Producer-Consumer 18Copyright ©: University of Illinois CS 241 Staff Chef = Producer Waiter= Consumer

Producer-Consumer insertPtr removePtr 19Copyright ©: University of Illinois CS 241 Staff Chef = Producer Waiter= Consumer What does the chef do with a new pizza? Where does the waiter take a pizza from?

Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 20Copyright ©: University of Illinois CS 241 Staff Insert pizza insertPtr

Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 21Copyright ©: University of Illinois CS 241 Staff Insert pizza

Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 22Copyright ©: University of Illinois CS 241 Staff Insert pizza

Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 23Copyright ©: University of Illinois CS 241 Staff Remove pizza removePtr

Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 24Copyright ©: University of Illinois CS 241 Staff Insert pizza

Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 25Copyright ©: University of Illinois CS 241 Staff Insert pizza

Producer-Consumer insertPtr removePtr BUFFER FULL: Producer must be blocked! Chef = Producer Waiter= Consumer 26Copyright ©: University of Illinois CS 241 Staff Insert pizza

Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 27Copyright ©: University of Illinois CS 241 Staff Remove pizza

Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 28Copyright ©: University of Illinois CS 241 Staff Remove pizza

Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 29Copyright ©: University of Illinois CS 241 Staff Remove pizza

Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 30Copyright ©: University of Illinois CS 241 Staff Remove pizza

Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 31Copyright ©: University of Illinois CS 241 Staff Remove pizza

Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 32Copyright ©: University of Illinois CS 241 Staff Remove pizza

Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 33Copyright ©: University of Illinois CS 241 Staff Remove pizza

Producer-Consumer insertPtr removePtr BUFFER EMPTY: Consumer must be blocked! Chef = Producer Waiter= Consumer 34Copyright ©: University of Illinois CS 241 Staff Remove pizza

Producer-Consumer Summary Producer  Insert items  Update insertion pointer Consumer  Execute destructive read on the buffer  Update removal pointer Both  Update information about how full/empty the buffer is Solution  Must allow multiple producers and consumers Copyright ©: University of Illinois CS 241 Staff35

Challenges Prevent buffer overflow Prevent buffer underflow Mutual exclusion when modifying the buffer data structure 36Copyright ©: University of Illinois CS 241 Staff

Solutions Prevent buffer overflow  Block producer when full  Counting semaphore to count #free slots  0  block producer Prevent buffer underflow Mutual exclusion when modifying the buffer data structure 37Copyright ©: University of Illinois CS 241 Staff

Solutions Prevent buffer overflow  Block producer when full  Counting semaphore to count #free slots  0  block producer Prevent buffer underflow  Block consumer when empty  Counting semaphore to count #items in buffer  0  block consumer Mutual exclusion when modifying the buffer data structure 38Copyright ©: University of Illinois CS 241 Staff

Solutions Prevent buffer overflow  Block producer when full  Counting semaphore to count #free slots  0  block producer Prevent buffer underflow  Block consumer when empty  Counting semaphore to count #items in buffer  0  block consumer Mutual exclusion when modifying the buffer data structure  Mutex protects shared buffer & pointers 39Copyright ©: University of Illinois CS 241 Staff

Assembling the solution Producer  sem_wait(slots), sem_signal(slots)  Initialize slots to N Consumer  sem_wait(items), sem_signal(items)  Initialize semaphore items to 0 Synchronization  mutex_lock(m), mutex_unlock(m) Buffer management  insertptr = (insertptr+1) % N  removalptr = (removalptr+1) % N Copyright ©: University of Illinois CS 241 Staff40

Producer-Consumer Code buffer[ insertPtr ] = data; insertPtr = (insertPtr + 1) % N; result = buffer[removePtr]; removePtr = (removePtr +1) % N; Copyright ©: University of Illinois CS 241 Staff41 Critical Section: move insert pointer Critical Section: move remove pointer

Producer-Consumer Code sem_wait(slots); mutex_lock(mutex); buffer[ insertPtr ] = data; insertPtr = (insertPtr + 1) % N; mutex_unlock(mutex); sem_signal(items); sem_wait(items); mutex_lock(mutex); result = buffer[removePtr]; removePtr = (removePtr +1) % N; mutex_unlock(mutex); sem_signal(slots); Copyright ©: University of Illinois CS 241 Staff42 Block if there are no free slots Block if there are no items to take Counting semaphore – check and decrement the number of free slots Counting semaphore – check and decrement the number of available items Done – increment the number of available items Done – increment the number of free slots

Consumer Pseudocode: getItem() sem_wait(items); mutex_lock(mutex); result = buffer[removePtr]; removePtr = (removePtr +1) % N; mutex_unlock(mutex); sem_signal(slots); Copyright ©: University of Illinois CS 241 Staff43 Error checking/EINTR handling not shown

Producer Pseudocode: putItem(data) sem_wait(slots); mutex_lock(mutex); buffer[ insertPtr ] = data; insertPtr = (insertPtr + 1) % N; mutex_unlock(mutex); sem_signal(items); Copyright ©: University of Illinois CS 241 Staff44 Error checking/EINTR handling not shown

Shared Resource Readers-Writers Problem

Shared Resource Readers-Writers Problem

Shared Resource Readers-Writers Problem

II. Reader-Writer Problem Readers read data Writers write data Rules  Multiple readers may read the data simultaneously  Only one writer can write the data at any time  A reader and a writer cannot access data simultaneously Locking table  Whether any two can be in the critical section simultaneously Copyright ©: University of Illinois CS 241 Staff48 ReaderWriter Reader OKNo WriterNo

reader() { while(TRUE) { ; sem_wait(mutex); readCount++; if(readCount == 1) sem_wait(writeBlock); sem_signal(mutex); /* Critical section */ access(resource); sem_wait(mutex); readCount--; if(readCount == 0) sem_signal(writeBlock); sem_post(mutex); } writer() { while(TRUE) { ; sem_wait(writeBlock); /* Critical section */ access(resource); sem_signal(writeBlock); } Reader-Writer: First Solution int readCount = 0; semaphore mutex = 1; semaphore writeBlock = 1;

reader() { while(TRUE) { ; sem_wait(mutex); readCount++; if(readCount == 1) sem_wait(writeBlock); sem_signal(mutex); /* Critical section */ access(resource); sem_wait(mutex); readCount--; if(readCount == 0) sem_signal(writeBlock); sem_post(mutex); } writer() { while(TRUE) { ; sem_wait(writeBlock); /* Critical section */ access(resource); sem_signal(writeBlock); } First reader competes with writers Last reader signals writers Reader-Writer: First Solution int readCount = 0; semaphore mutex = 1; semaphore writeBlock = 1; First reader blocks writers Last reader unblocks writers Writer blocks all readers

reader() { while(TRUE) { ; sem_wait(mutex); readCount++; if(readCount == 1) sem_wait(writeBlock); sem_signal(mutex); /* Critical section */ access(resource); sem_wait(mutex); readCount--; if(readCount == 0) sem_signal(writeBlock); sem_post(mutex); } writer() { while(TRUE) { ; sem_wait(writeBlock); /* Critical section */ access(resource); sem_signal(writeBlock); } Any writer must wait for all readers → Readers can starve writers → Updates can be delayed forever → Not desirable! Reader-Writer: First Solution int readCount = 0; semaphore mutex = 1; semaphore writeBlock = 1; First reader blocks writers Last reader unblocks writers

reader() { while(TRUE) { ; sem_wait(readBlock); sem_wait(mutex1); readCount++; if(readCount == 1) sem_wait(writeBlock); sem_signal(mutex1); sem_signal(readBlock); access(resource); sem_wait(mutex1); readCount--; if(readCount == 0) sem_signal(writeBlock); sem_signal(mutex1); } writer() { while(TRUE) { ; sem_wait(mutex2); writeCount++; if(writeCount == 1) sem_wait(readBlock); sem_signal(mutex2); sem_wait(writeBlock); access(resource); sem_signal(writeBlock); sem_wait(mutex2); writeCount--; if(writeCount == 0) sem_signal(readBlock); sem_signal(mutex2); } Reader-Writer: Second Solution int readCount=0, writeCount=0; semaphore mutex1=1, mutex2=1; Semaphore readBlock=1,writeBlock=1

reader() { while(TRUE) { ; sem_wait(readBlock); sem_wait(mutex1); readCount++; if(readCount == 1) sem_wait(writeBlock); sem_signal(mutex1); sem_signal(readBlock); access(resource); sem_wait(mutex1); readCount--; if(readCount == 0) sem_signal(writeBlock); sem_signal(mutex1); } writer() { while(TRUE) { ; sem_wait(mutex2); writeCount++; if(writeCount == 1) sem_wait(readBlock); sem_signal(mutex2); sem_wait(writeBlock); access(resource); sem_signal(writeBlock); sem_wait(mutex2); writeCount--; if(writeCount == 0) sem_signal(readBlock); sem_signal(mutex2); } Reader-Writer: Second Solution int readCount=0, writeCount=0; semaphore mutex1=1, mutex2=1; Semaphore readBlock=1,writeBlock=1 Wait for writers First writer blocks readers Last writer unblocks readers

reader() { while(TRUE) { ; sem_wait(readBlock); sem_wait(mutex1); readCount++; if(readCount == 1) sem_wait(writeBlock); sem_signal(mutex1); sem_signal(readBlock); access(resource); sem_wait(mutex1); readCount--; if(readCount == 0) sem_signal(writeBlock); sem_signal(mutex1); } writer() { while(TRUE) { ; sem_wait(mutex2); writeCount++; if(writeCount == 1) sem_wait(readBlock); sem_signal(mutex2); sem_wait(writeBlock); access(resource); sem_signal(writeBlock); sem_wait(mutex2); writeCount--; if(writeCount == 0) sem_signal(readBlock); sem_signal(mutex2); } Reader-Writer: Second Solution int readCount=0, writeCount=0; semaphore mutex1=1, mutex2=1; Semaphore readBlock=1,writeBlock=1 Writers can starve readers → Reads can be delayed forever → Not desirable, either!

Better R-W solution idea Idea: serve requests in order  Once a writer requests access, any entering readers have to block until the writer is done Advantage? Disadvantage? 55Copyright ©: University of Illinois CS 241 Staff

reader() { while(TRUE) { ; sem_wait(writePending); sem_wait(readBlock); sem_wait(mutex1); readCount++; if(readCount == 1) sem_wait(writeBlock); sem_signal(mutex1); sem_signal(readBlock); sem_signal(writePending); access(resource); sem_wait(mutex1); readCount--; if(readCount == 0) sem_signal(writeBlock); sem_signal(mutex1); } writer() { while(TRUE) { ; sem_wait(writePending); sem_wait(mutex2); writeCount++; if(writeCount == 1) sem_wait(readBlock); sem_signal(mutex2); sem_wait(writeBlock); access(resource); sem_signal(writeBlock); sem_signal(writePending); sem_wait(mutex2); writeCount--; if(writeCount == 0) sem_signal(readBlock); sem_signal(mutex2); } Reader-Writer: Fairer Solution? int readCount = 0, writeCount = 0; semaphore mutex1 = 1, mutex2 = 1; semaphore readBlock = 1, writeBlock = 1, writePending = 1;

reader() { while(TRUE) { ; sem_wait(writePending); sem_wait(readBlock); sem_wait(mutex1); readCount++; if(readCount == 1) sem_wait(writeBlock); sem_signal(mutex1); sem_signal(readBlock); sem_signal(writePending); access(resource); sem_wait(mutex1); readCount--; if(readCount == 0) sem_signal(writeBlock); sem_signal(mutex1); } writer() { while(TRUE) { ; sem_wait(writePending); sem_wait(mutex2); writeCount++; if(writeCount == 1) sem_wait(readBlock); sem_signal(mutex2); sem_wait(writeBlock); access(resource); sem_signal(writeBlock); sem_signal(writePending); sem_wait(mutex2); writeCount--; if(writeCount == 0) sem_signal(readBlock); sem_signal(mutex2); } Reader-Writer: Fairer Solution? int readCount = 0, writeCount = 0; semaphore mutex1 = 1, mutex2 = 1; semaphore readBlock = 1, writeBlock = 1, writePending = 1; Wait for a pending writers that arrived before me Writer blocks subsequent readers

4131 reader() { while(TRUE) { ; sem_wait(writePending); sem_wait(readBlock); sem_wait(mutex1); readCount++; if(readCount == 1) sem_wait(writeBlock); sem_signal(mutex1); sem_signal(readBlock); sem_signal(writePending); access(resource); sem_wait(mutex1); readCount--; if(readCount == 0) sem_signal(writeBlock); sem_signal(mutex1); } writer() { while(TRUE) { ; sem_wait(writePending); sem_wait(mutex2); writeCount++; if(writeCount == 1) sem_wait(readBlock); sem_signal(mutex2); sem_wait(writeBlock); access(resource); sem_signal(writeBlock); sem_signal(writePending); sem_wait(mutex2); writeCount--; if(writeCount == 0) sem_signal(readBlock); sem_signal(mutex2); } Reader-Writer: Fairer Solution? int readCount = 0, writeCount = 0; semaphore mutex1 = 1, mutex2 = 1; semaphore readBlock = 1, writeBlock = 1, writePending = 1;

431 reader() { while(TRUE) { ; sem_wait(writePending); sem_wait(readBlock); sem_wait(mutex1); readCount++; if(readCount == 1) sem_wait(writeBlock); sem_signal(mutex1); sem_signal(readBlock); sem_signal(writePending); access(resource); sem_wait(mutex1); readCount--; if(readCount == 0) sem_signal(writeBlock); sem_signal(mutex1); } writer() { while(TRUE) { ; sem_wait(writePending); sem_wait(mutex2); writeCount++; if(writeCount == 1) sem_wait(readBlock); sem_signal(mutex2); sem_wait(writeBlock); access(resource); sem_signal(writeBlock); sem_signal(writePending); sem_wait(mutex2); writeCount--; if(writeCount == 0) sem_signal(readBlock); sem_signal(mutex2); } Reader-Writer: Fairer Solution? int readCount = 0, writeCount = 0; semaphore mutex1 = 1, mutex2 = 1; semaphore readBlock = 1, writeBlock = 1, writePending = 1; 1

reader() { while(TRUE) { ; sem_wait(writePending); sem_wait(readBlock); sem_wait(mutex1); readCount++; if(readCount == 1) sem_wait(writeBlock); sem_signal(mutex1); sem_signal(readBlock); sem_signal(writePending); access(resource); sem_wait(mutex1); readCount--; if(readCount == 0) sem_signal(writeBlock); sem_signal(mutex1); } writer() { while(TRUE) { ; sem_wait(writePending); sem_wait(mutex2); writeCount++; if(writeCount == 1) sem_wait(readBlock); sem_signal(mutex2); sem_wait(writeBlock); access(resource); sem_signal(writeBlock); sem_signal(writePending); sem_wait(mutex2); writeCount--; if(writeCount == 0) sem_signal(readBlock); sem_signal(mutex2); } Reader-Writer: Fairer Solution? int readCount = 0, writeCount = 0; semaphore mutex1 = 1, mutex2 = 1; semaphore readBlock = 1, writeBlock = 1, writePending = 1; When a reader arrives and a writer is waiting, the reader is suspended behind the writer → Less concurrency → Lower performance

Summary Classic synchronization problems  Producer-Consumer Problem  Reader-Writer Problem Saved for next time:  Sleeping Barber’s Problem  Dining Philosophers Problem 61Copyright ©: University of Illinois CS 241 Staff

Dining Philosophers N philosophers and N forks  Philosophers eat/think  Eating needs 2 forks  Pick one fork at a time 2 62Copyright ©: University of Illinois CS 241 Staff