Download presentation
Presentation is loading. Please wait.
Published byNorman Murphy Modified over 9 years ago
1
Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1
2
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
3
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
4
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
5
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
6
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
7
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
8
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;
9
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
10
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
11
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
12
Classical Synchronization Problems 12Copyright ©: University of Illinois CS 241 Staff
13
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
14
Chefs cook items and put them on a conveyer belt 14Copyright ©: University of Illinois CS 241 Staff Waiters pick items off the belt
15
Now imagine many chefs! 15Copyright ©: University of Illinois CS 241 Staff And many waiters!
16
A potential mess! 16Copyright ©: University of Illinois CS 241 Staff
17
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
18
Producer-Consumer 18Copyright ©: University of Illinois CS 241 Staff Chef = Producer Waiter= Consumer
19
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?
20
Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 20Copyright ©: University of Illinois CS 241 Staff Insert pizza insertPtr
21
Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 21Copyright ©: University of Illinois CS 241 Staff Insert pizza
22
Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 22Copyright ©: University of Illinois CS 241 Staff Insert pizza
23
Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 23Copyright ©: University of Illinois CS 241 Staff Remove pizza removePtr
24
Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 24Copyright ©: University of Illinois CS 241 Staff Insert pizza
25
Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 25Copyright ©: University of Illinois CS 241 Staff Insert pizza
26
Producer-Consumer insertPtr removePtr BUFFER FULL: Producer must be blocked! Chef = Producer Waiter= Consumer 26Copyright ©: University of Illinois CS 241 Staff Insert pizza
27
Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 27Copyright ©: University of Illinois CS 241 Staff Remove pizza
28
Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 28Copyright ©: University of Illinois CS 241 Staff Remove pizza
29
Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 29Copyright ©: University of Illinois CS 241 Staff Remove pizza
30
Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 30Copyright ©: University of Illinois CS 241 Staff Remove pizza
31
Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 31Copyright ©: University of Illinois CS 241 Staff Remove pizza
32
Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 32Copyright ©: University of Illinois CS 241 Staff Remove pizza
33
Producer-Consumer insertPtr removePtr Chef = Producer Waiter= Consumer 33Copyright ©: University of Illinois CS 241 Staff Remove pizza
34
Producer-Consumer insertPtr removePtr BUFFER EMPTY: Consumer must be blocked! Chef = Producer Waiter= Consumer 34Copyright ©: University of Illinois CS 241 Staff Remove pizza
35
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
36
Challenges Prevent buffer overflow Prevent buffer underflow Mutual exclusion when modifying the buffer data structure 36Copyright ©: University of Illinois CS 241 Staff
37
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
38
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
39
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
40
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
41
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
42
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
43
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
44
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
45
Shared Resource Readers-Writers Problem
46
Shared Resource Readers-Writers Problem
47
Shared Resource Readers-Writers Problem
48
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
49
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;
50
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
51
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
52
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
53
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
54
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!
55
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
56
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;
57
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
58
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;
59
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
60
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
61
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
62
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
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.