100 likes | 252 Views
Chapter 31 Semaphores. Chien -Chung Shen CIS, UD cshen@cis.udel.edu. Basic Ideas of Semaphores. Locks and condition variables for concurrency Invented by Edsger Dijkstra as a synchronization primitive , which can be used as both locks and condition variables
E N D
Chapter 31Semaphores Chien-Chung Shen CIS, UD cshen@cis.udel.edu
Basic Ideas of Semaphores • Locks and condition variables for concurrency • Invented by EdsgerDijkstraas a synchronization primitive, which can be used as both locks and condition variables • Use of semaphores and implementation of semaphores
Definition • An object with an integer value and two operations, sem_wait() and sem_post() • Initial value of a semaphore determines its behavior sem_t s; sem_init(&s, 0, X); // 0: shared between threads in the same process // X: initial value intsem_wait(sem_t*s) { decrement the value of semaphore s by 1 wait until value of s is greater than or equal to 0 } intsem_post(sem_t*s) { increment the value of semaphore s by 1 if there are one or more threads waiting, wake one }
Features • sem_wait() will either return right away (because value of semaphore was 1or higher when we called sem_wait()), or it will cause the caller to suspend execution waiting for a subsequent post. Multiple calling threads may call into sem_wait(), and thus all be queued waiting to be woken • sem_post() does not wait. Rather, it simply increments the value of semaphore and then, if there is any thread waiting, wakes one of them up • Value of semaphore, when negative, is equal to the number of waiting threads
Binary Semaphore as Lock • Using semaphore as lock sem_t m; sem_init(&m, 0, X); // initialize semaphore to X; sem_wait(&m); // critical section here sem_post(&m); • X = ? • Tables 31.1 (p. 3) and 31.2 (p. 4)
Semaphore as Condition Variable • Used when a thread waits for something to happen, and a different thread makes that something happen and wakes the waiting thread sem_t s; // parent waits fro child void child(void *arg) { printf("child\n");sem_post(&s); // signal here: child is done return NULL; return NULL; } int main(intargc, char *argv[]) { sem_init(&s, 0, X); // what should X be? printf("parent: begin\n"); pthread_t c; Pthread_create(c, NULL, child, NULL); sem_wait(&s); // wait here for child printf("parent: end\n"); return 0; } • Tables 31.3 (p. 5) and 31.4 (p. 6)
Producer/Consumer (Bounded Buffer) • Buffer of 1 slot - producer first waits for a buffer to become empty in order to put data into it, and the consumer similarly waits for a buffer to become filled before using it • single producer & single consumer • multiple producers & multiple consumers • Buffer of 10 slots • single producer & single consumer • multiple producers & multiple consumers
Dining Philosophers Philosopher(int p) { while (1) { think(); getforks(p); eat(); putforks(p); } } void getforks(int p) { sem_wait(forks[left(p)]); sem_wait(forks[right(p)]); } void putforks(int p) { sem_post(forks[left(p)]); sem_post(forks[right(p)]); } sem_t forks[5]; int left(int p) { return p; } int right(int p) { return (p+1)%5; } void getforks(int p) { if (p == 4) { sem_wait(forks[right(p)]); sem_wait(forks[left(p)]); } else { sem_wait(forks[left(p)]); sem_wait(forks[right(p)]); } }