condition variables revisited copyright ©: university of illinois cs 241 staff1

60
Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff 1

Upload: norman-murphy

Post on 24-Dec-2015

218 views

Category:

Documents


0 download

TRANSCRIPT

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

Condition Variables Revisited

Copyright ©: University of Illinois CS 241 Staff 1

Page 2: 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 Staff 2

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

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

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

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

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

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

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

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

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

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

Classical Synchronization Problems

12Copyright ©: University of Illinois CS 241 Staff

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

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

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

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

A potential mess!

16Copyright ©: University of Illinois CS 241 Staff

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

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

Producer-Consumer

18Copyright ©: University of Illinois CS 241 Staff

Chef = ProducerWaiter = Consumer

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Shared Resource

Readers-Writers Problem

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

Shared Resource

Readers-Writers Problem

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

Shared Resource

Readers-Writers Problem

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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