![Page 1: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/1.jpg)
Condition Variables Revisited
Copyright ©: University of Illinois CS 241 Staff 1
![Page 2: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/2.jpg)
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 Staff 2
![Page 3: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/3.jpg)
Inside a condition variable
struct pthread_cond {
int waiting;
handle_t semaphore;
};
Copyright ©: University of Illinois CS 241 Staff 3
Number of threads waiting on the condition variable
A semaphore for synchronization
![Page 4: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/4.jpg)
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 Staff 4
pthread_mutex_lock is always called before pthread_cond_wait to acquire lock
Hav
e lo
ck
int pthread_cond_signal(pthread_cond_t *cond) {
if (cond->waiting)
semrel(cond->semaphore, 1);
return 0;
}
Hav
e lo
ck
Thread always has lock when returning from pthread_cond_wait
![Page 5: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/5.jpg)
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 Staff 5
![Page 6: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/6.jpg)
Example
#include <stdio.h>
#include <pthread.h>
#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 Staff 6
![Page 7: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/7.jpg)
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 Staff 7
![Page 8: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/8.jpg)
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 Staff 8
pthread_mutex_t data_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cont_t data_cond = PTHREAD_COND_INITIALIZER;
![Page 9: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/9.jpg)
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 Staff 9
![Page 10: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/10.jpg)
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 Staff 10
![Page 11: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/11.jpg)
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 Staff 11
![Page 12: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/12.jpg)
Classical Synchronization Problems
12Copyright ©: University of Illinois CS 241 Staff
![Page 13: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/13.jpg)
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
![Page 14: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/14.jpg)
Chefs cook items and put them on a conveyer belt
14Copyright ©: University of Illinois CS 241 Staff
Waiters pick items off the belt
![Page 15: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/15.jpg)
Now imagine many chefs!
15Copyright ©: University of Illinois CS 241 Staff
And many waiters!
![Page 16: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/16.jpg)
A potential mess!
16Copyright ©: University of Illinois CS 241 Staff
![Page 17: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/17.jpg)
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 = ProducerWaiter = Consumer
17Copyright ©: University of Illinois CS 241 Staff
![Page 18: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/18.jpg)
Producer-Consumer
18Copyright ©: University of Illinois CS 241 Staff
Chef = ProducerWaiter = Consumer
![Page 19: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/19.jpg)
Producer-Consumer
insertPtr
removePtr
19Copyright ©: University of Illinois CS 241 Staff
Chef = ProducerWaiter = Consumer
What does the chef do with a
new pizza?
Where does the waiter take a pizza from?
![Page 20: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/20.jpg)
Producer-Consumer
insertPtr
removePtr
Chef = ProducerWaiter = Consumer
20Copyright ©: University of Illinois CS 241 Staff
Insert pizza
insertPtr
![Page 21: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/21.jpg)
Producer-Consumer
insertPtr
removePtr
Chef = ProducerWaiter = Consumer
21Copyright ©: University of Illinois CS 241 Staff
Insert pizza
![Page 22: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/22.jpg)
Producer-Consumer
insertPtr
removePtr
Chef = ProducerWaiter = Consumer
22Copyright ©: University of Illinois CS 241 Staff
Insert pizza
![Page 23: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/23.jpg)
Producer-Consumer
insertPtr
removePtr
Chef = ProducerWaiter = Consumer
23Copyright ©: University of Illinois CS 241 Staff
Remove pizza
removePtr
![Page 24: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/24.jpg)
Producer-Consumer
insertPtr
removePtr
Chef = ProducerWaiter = Consumer
24Copyright ©: University of Illinois CS 241 Staff
Insert pizza
![Page 25: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/25.jpg)
Producer-Consumer
insertPtr
removePtr
Chef = ProducerWaiter = Consumer
25Copyright ©: University of Illinois CS 241 Staff
Insert pizza
![Page 26: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/26.jpg)
Producer-Consumer
insertPtr
removePtr
BUFFER FULL: Producer must be blocked!
Chef = ProducerWaiter = Consumer
26Copyright ©: University of Illinois CS 241 Staff
Insert pizza
![Page 27: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/27.jpg)
Producer-Consumer
insertPtrremovePtr
Chef = ProducerWaiter = Consumer
27Copyright ©: University of Illinois CS 241 Staff
Remove pizza
![Page 28: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/28.jpg)
Producer-Consumer
insertPtr
removePtr
Chef = ProducerWaiter = Consumer
28Copyright ©: University of Illinois CS 241 Staff
Remove pizza
![Page 29: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/29.jpg)
Producer-Consumer
insertPtr
removePtr
Chef = ProducerWaiter = Consumer
29Copyright ©: University of Illinois CS 241 Staff
Remove pizza
![Page 30: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/30.jpg)
Producer-Consumer
insertPtr
removePtr
Chef = ProducerWaiter = Consumer
30Copyright ©: University of Illinois CS 241 Staff
Remove pizza
![Page 31: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/31.jpg)
Producer-Consumer
insertPtr
removePtr
Chef = ProducerWaiter = Consumer
31Copyright ©: University of Illinois CS 241 Staff
Remove pizza
![Page 32: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/32.jpg)
Producer-Consumer
insertPtr
removePtr
Chef = ProducerWaiter = Consumer
32Copyright ©: University of Illinois CS 241 Staff
Remove pizza
![Page 33: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/33.jpg)
Producer-Consumer
insertPtr
removePtr
Chef = ProducerWaiter = Consumer
33Copyright ©: University of Illinois CS 241 Staff
Remove pizza
![Page 34: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/34.jpg)
Producer-Consumer
insertPtr
removePtr
BUFFER EMPTY: Consumer must be blocked!
Chef = ProducerWaiter = Consumer
34Copyright ©: University of Illinois CS 241 Staff
Remove pizza
![Page 35: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/35.jpg)
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 Staff 35
![Page 36: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/36.jpg)
Challenges
Prevent buffer overflow Prevent buffer underflow Mutual exclusion when modifying the
buffer data structure
36Copyright ©: University of Illinois CS 241 Staff
![Page 37: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/37.jpg)
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
![Page 38: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/38.jpg)
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
![Page 39: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/39.jpg)
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
![Page 40: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/40.jpg)
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 Staff 40
![Page 41: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/41.jpg)
Producer-Consumer Code
buffer[ insertPtr ] = data;
insertPtr = (insertPtr + 1) % N;
result = buffer[removePtr];
removePtr = (removePtr +1) % N;
Copyright ©: University of Illinois CS 241 Staff 41
Critical Section: move insert pointer
Critical Section: move remove pointer
![Page 42: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/42.jpg)
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 Staff 42
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
![Page 43: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/43.jpg)
Shared Resource
Readers-Writers Problem
![Page 44: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/44.jpg)
Shared Resource
Readers-Writers Problem
![Page 45: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/45.jpg)
Shared Resource
Readers-Writers Problem
![Page 46: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/46.jpg)
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 Staff 48
Reader Writer
Reader OK No
Writer No No
![Page 47: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/47.jpg)
reader() { while(TRUE) { <other stuff>; 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) { <other computing>; sem_wait(writeBlock); /* Critical section */ access(resource); sem_signal(writeBlock); }}
Reader-Writer: First Solutionint readCount = 0;semaphore mutex = 1;semaphore writeBlock = 1;
![Page 48: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/48.jpg)
reader() { while(TRUE) { <other stuff>; 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) { <other computing>; sem_wait(writeBlock); /* Critical section */ access(resource); sem_signal(writeBlock); }}
First reader competes with writersLast reader signals writers
Reader-Writer: First Solutionint readCount = 0;semaphore mutex = 1;semaphore writeBlock = 1;
First reader blocks writers
Last reader unblocks writers
Writer blocks all readers
![Page 49: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/49.jpg)
reader() { while(TRUE) { <other stuff>; 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) { <other computing>; 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 Solutionint readCount = 0;semaphore mutex = 1;semaphore writeBlock = 1;
First reader blocks writers
Last reader unblocks writers
![Page 50: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/50.jpg)
reader() { while(TRUE) { <other computing>; 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) { <other computing>; 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
![Page 51: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/51.jpg)
reader() { while(TRUE) { <other computing>; 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) { <other computing>; 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
![Page 52: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/52.jpg)
reader() { while(TRUE) { <other computing>; 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) { <other computing>; 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!
![Page 53: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/53.jpg)
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
![Page 54: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/54.jpg)
reader() { while(TRUE) { <other computing>; 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) { <other computing>; 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;
![Page 55: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/55.jpg)
reader() { while(TRUE) { <other computing>; 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) { <other computing>; 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
![Page 56: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/56.jpg)
4131reader() { while(TRUE) { <other computing>; 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) { <other computing>; 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;
![Page 57: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/57.jpg)
43
1
reader() { while(TRUE) { <other computing>; 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) { <other computing>; 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
![Page 58: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/58.jpg)
reader() { while(TRUE) { <other computing>; 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) { <other computing>; 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
![Page 59: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/59.jpg)
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
![Page 60: Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1](https://reader035.vdocument.in/reader035/viewer/2022062407/56649dc95503460f94abf6d9/html5/thumbnails/60.jpg)
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