Copyright ©: University of Illinois CS 241 Staff1 Synchronization and Semaphores.

Slides:



Advertisements
Similar presentations
Operating Systems Semaphores II
Advertisements

CS Lecture 4 Programming with Posix Threads and Java Threads George Mason University Fall 2009.
Prepared By Sarath S Menon S6 CSE.  Imagine a scenario in which there exists two Distinct processes both operating on a single shared data area.  One.
Threads Programming Thread creation Synchronization.
Pthreads & Concurrency. Acknowledgements  The material in this tutorial is based in part on: POSIX Threads Programming, by Blaise Barney.
Multi-core Programming Programming with Posix Threads.
PTHREADS These notes are from LLNL Pthreads Tutorial
Concurrency, Race Conditions, Mutual Exclusion, Semaphores, Monitors, Deadlocks Chapters 2 and 6 Tanenbaum’s Modern OS.
Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.
Computer Architecture II 1 Computer architecture II Programming: POSIX Threads OpenMP.
8-1 JMH Associates © 2004, All rights reserved Windows Application Development Chapter 10 - Supplement Introduction to Pthreads for Application Portability.
Lecture 18 Threaded Programming CPE 401 / 601 Computer Network Systems slides are modified from Dave Hollinger.
Threads© Dr. Ayman Abdel-Hamid, CS4254 Spring CS4254 Computer Network Architecture and Programming Dr. Ayman A. Abdel-Hamid Computer Science Department.
Pthread II. Outline Join Mutex Variables Condition Variables.
Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1.
Netprog Threads Programming1 Threads Programming Refs: Chapter 23.
Pthread (continue) General pthread program structure –Encapsulate parallel parts (can be almost the whole program) in functions. –Use function arguments.
Introduction to Pthreads. Pthreads Pthreads is a POSIX standard for describing a thread model, it specifies the API and the semantics of the calls. Model.
Atomic Operations David Monismith cs550 Operating Systems.
Thread Synchronization with Semaphores
Multi-threaded Programming with POSIX Threads CSE331 Operating Systems Design.
Threads and Thread Control Thread Concepts Pthread Creation and Termination Pthread synchronization Threads and Signals.
CS345 Operating Systems Threads Assignment 3. Process vs. Thread process: an address space with 1 or more threads executing within that address space,
What is a thread? process: an address space with 1 or more threads executing within that address space, and the required system resources for those threads.
Copyright ©: Nahrstedt, Angrave, Abdelzaher1 Semaphore and Mutex Operations.
Programming with POSIX* Threads Intel Software College.
Linux Programming –Threads CS Threads Review Threads in the same address space –share everything in the address space –lighter than process –no.
Condition Variables u A condition variable is used to wait until a particular condition is true  like in a monitor u Always use condition variables together.
Pthreads: A shared memory programming model
S -1 Posix Threads. S -2 Thread Concepts Threads are "lightweight processes" –10 to 100 times faster than fork() Threads share: –process instructions,
Threads and Locking Ioctl operations. Threads Lightweight processes What’s wrong with processes? –fork() is expensive – 10 to 100 times slower –Inter.
Threads Chapter 26. Threads Light-weight processes Each process can have multiple threads of concurrent control. What’s wrong with processes? fork() is.
1 Pthread Programming CIS450 Winter 2003 Professor Jinhua Guo.
Thread API Xiaohua Lu Office : CS 3310 Tel. : Office hours: 11-12,3-5 T,TR.
POSIX Synchronization Introduction to Operating Systems: Discussion Module 5.
POSIX Threads HUJI Spring 2011.
Synchronizing Threads with Semaphores
2.3 interprocess communcation (IPC) (especially via shared memory & controlling access to it)
CS252: Systems Programming Ninghui Li Based on Slides by Prof. Gustavo Rodriguez-Rivera Topic 11: Thread-safe Data Structures, Semaphores.
Pthreads #include pthread_t tid ; //thread id. pthread_attr_t attr ; void *sleeping(void *); /* thread routine */ main() { int time = 2 ; pthread_create(&tid,
U NIVERSITY OF M ASSACHUSETTS A MHERST Department of Computer Science Software Systems Advanced Synchronization Emery Berger and Mark Corner University.
CS252: Systems Programming Ninghui Li Based on Slides by Prof. Gustavo Rodriguez-Rivera Topic 12: Thread-safe Data Structures, Semaphores.
1 Condition Variables CS 241 Prof. Brighten Godfrey March 16, 2012 University of Illinois.
Chapter 6 P-Threads. Names The naming convention for a method/function/operation is: – pthread_thing_operation(..) – Where thing is the object used (such.
CS252: Systems Programming Ninghui Li Based on Slides by Prof. Gustavo Rodriguez-Rivera Topic 13: Condition Variable, Read/Write Lock, and Deadlock.
PThread Synchronization. Thread Mechanisms Birrell identifies four mechanisms commonly used in threading systems –Thread creation –Mutual exclusion (mutex)
CS 360 pthreads Condition Variables for threads. Page 2 CS 360, WSU Vancouver What is the issue? Creating a thread to perform a task and then joining.
Working with Pthreads. Operations on Threads int pthread_create (pthread_t *thread, const pthread_attr_t *attr, void * (*routine)(void*), void* arg) Creates.
Web Server Architecture Client Main Thread for(j=0;j
pThread synchronization
Case Study: Pthread Synchronization Dr. Yingwu Zhu.
Synchronization and Semaphores
CS 537 – Introduction to Operating Systems
Principles of Operating Systems Lecture 11
Shared-Memory Programming with Threads
Threads Threads.
Netprog: Threads Programming
PTHREADS These notes are from LLNL Pthreads Tutorial
Thread synchronization
Lecture 14: Pthreads Mutex and Condition Variables
PTHREADS AND SEMAPHORES
Synchronization and Semaphores
Pthread Prof. Ikjun Yeom TA – Mugyo
Synchronization Primitives – Semaphore and Mutex
Lecture 14: Pthreads Mutex and Condition Variables
Synchronization.
Synchronization.
Lecture 20: Synchronization
Lecture 12 CV and Semaphores
POSIX Threads(pthreads)
Presentation transcript:

Copyright ©: University of Illinois CS 241 Staff1 Synchronization and Semaphores

Synchronization Primatives Counting Semaphores  Permit a limited number of threads to execute a section of the code Binary Semaphores - Mutexes  Permit only one thread to execute a section of the code Condition Variables  Communicate information about the state of shared data Copyright ©: University of Illinois CS 241 Staff2

POSIX Semaphores Named Semaphores  Provides synchronization between unrelated process and related process as well as between threads  Kernel persistence  System-wide and limited in number  Uses sem_open Unnamed Semaphores  Provides synchronization between threads and between related processes  Thread-shared or process-shared  Uses sem_init 3Copyright ©: University of Illinois CS 241 Staff

POSIX Semaphores Data type  Semaphore is a variable of type sem_t Include Atomic Operations int sem_init(sem_t *sem, int pshared, unsigned value); int sem_destroy(sem_t *sem); int sem_post(sem_t *sem); int sem_trywait(sem_t *sem); int sem_wait(sem_t *sem); 4Copyright ©: University of Illinois CS 241 Staff

Unnamed Semaphores #include int sem_init(sem_t *sem, int pshared, unsigned value); Initialize an unnamed semaphore Returns  0 on success  -1 on failure, sets errno Parameters  sem : Target semaphore  pshared : 0: only threads of the creating process can use the semaphore Non-0: other processes can use the semaphore  value : Initial value of the semaphore You cannot make a copy of a semaphore variable!!! 5Copyright ©: University of Illinois CS 241 Staff

Sharing Semaphores Sharing semaphores between threads within a process is easy, use pshared==0 A non-zero pshared allows any process that can access the semaphore to use it  Places the semaphore in the global (OS) environment  Forking a process creates copies of any semaphore it has Note: unnamed semaphores are not shared across unrelated processes 6Copyright ©: University of Illinois CS 241 Staff

sem_init can fail On failure  sem_init returns -1 and sets errno sem_t semA; if (sem_init(&semA, 0, 1) == -1) perror(“Failed to initialize semaphore semA”); Value > sem_value_max Resources exhausted Insufficient privileges EINVAL ENOSPC EPERM cause errno 7Copyright ©: University of Illinois CS 241 Staff

Semaphore Operations #include int sem_destroy(sem_t *sem); Destroy an semaphore Returns  0 on success  -1 on failure, sets errno Parameters  sem : Target semaphore Notes  Can destroy a sem_t only once  Destroying a destroyed semaphore gives undefined results  Destroying a semaphore on which a thread is blocked gives undefined results 8Copyright ©: University of Illinois CS 241 Staff

Semaphore Operations #include int sem_post(sem_t *sem); Unlock a semaphore - same as signal Returns  0 on success  -1 on failure, sets errno ( == EINVAL if semaphore doesn’t exist) Parameters  sem : Target semaphore sem > 0: no threads were blocked on this semaphore, the semaphore value is incremented sem == 0: one blocked thread will be allowed to run 9Copyright ©: University of Illinois CS 241 Staff

Semaphore Operations #include int sem_wait(sem_t *sem); Lock a semaphore  Blocks if semaphore value is zero Returns  0 on success  -1 on failure, sets errno ( == EINTR if interrupted by a signal) Parameters  sem : Target semaphore sem > 0: thread acquires lock sem == 0: thread blocks 10Copyright ©: University of Illinois CS 241 Staff

Semaphore Operations #include int sem_trywait(sem_t *sem); Test a semaphore’s current condition  Does not block Returns  0 on success  -1 on failure, sets errno ( == AGAIN if semaphore already locked) Parameters  sem : Target semaphore sem > 0: thread acquires lock sem == 0: thread returns 11Copyright ©: University of Illinois CS 241 Staff

Example: bank balance Protect shared variable balance with a semaphore when used in:  decshared Decrements current value of balance  incshared increments the balance Copyright ©: University of Illinois CS 241 Staff12

Example: bank balance int decshared() { while (sem_wait(&balance_sem) == -1) if (errno != EINTR) return -1; balance--; return sem_post(&balance_sem); } int incshared() { while (sem_wait(&balance_sem) == -1) if (errno != EINTR) return -1; balance++; return sem_post(&balance_sem); } Copyright ©: University of Illinois CS 241 Staff13

Example: bank balance #include static int balance = 0; static sem_t bal_sem; int initshared(int val) { if (sem_init(&bal_sem, 0, 1) == -1) return -1; balance = val; return 0; } pshared value 14Copyright ©: University of Illinois CS 241 Staff

Example: bank balance int decshared() { while (sem_wait(&bal_sem) == -1) if (errno != EINTR) return -1; balance--; return sem_post(&bal_sem); } int incshared() { while (sem_wait(&bal_sem) == -1) if (errno != EINTR) return -1; balance++; return sem_post(&bal_sem); } Which one is going first? 15Copyright ©: University of Illinois CS 241 Staff

Advanced Semaphores int semget(key_t key, int nsems, int semflg); Get set of semaphores int semop(int semid, struct sembuf *sops, unsigned int nsops); Atomically perform a user-defined array of semaphore operations on the set of semaphores Copyright ©: University of Illinois CS 241 Staff16

Pthread Synchronization Two primitives  Mutex Semaphore with maximum value 1  Condition variable Provides a shared signal Combined with a mutex for synchronization Copyright ©: University of Illinois CS 241 Staff17

Pthread Mutex States  Locked Some thread holds the mutex  Unlocked No thread holds the mutex When several threads compete  One wins  The rest block Queue of blocked threads Copyright ©: University of Illinois CS 241 Staff18

Mutex Variables A typical sequence in the use of a mutex 1. Create and initialize mutex 2. Several threads attempt to lock mutex 3. Only one succeeds and now owns mutex 4. The owner performs some set of actions 5. The owner unlocks mutex 6. Another thread acquires mutex and repeats the process 7. Finally mutex is destroyed Copyright ©: University of Illinois CS 241 Staff19

Creating a mutex #include int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); Initialize a pthread mutex: the mutex is initially unlocked Returns  0 on success  Error number on failure EAGAIN: The system lacked the necessary resources; ENOMEM: Insufficient memory ; EPERM: Caller does not have privileges; EBUSY: An attempt to re- initialise a mutex; EINVAL: The value specified by attr is invalid Parameters  mutex: Target mutex  attr: NULL: the default mutex attributes are used Non-NULL: initializes with specified attributes 20Copyright ©: University of Illinois CS 241 Staff

Creating a mutex Default attributes  Use PTHREAD_MUTEX_INITIALIZER Statically allocated Equivalent to dynamic initialization by a call to pthread_mutex_init() with parameter attr specified as NULL No error checks are performed 21Copyright ©: University of Illinois CS 241 Staff

Destroying a mutex #include int pthread_mutex_destroy(pthread_mutex_t *mutex); Destroy a pthread mutex Returns  0 on success  Error number on failure EBUSY: An attempt to re-initialise a mutex; EINVAL: The value specified by attr is invalid Parameters  mutex: Target mutex 22Copyright ©: University of Illinois CS 241 Staff

Locking/unlocking a mutex #include int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex); Returns  0 on success  Error number on failure EBUSY: already locked; EINVAL: Not an initialised mutex; EDEADLK: The current thread already owns the mutex; EPERM: The current thread does not own the mutex 23Copyright ©: University of Illinois CS 241 Staff

Simple Example #include static pthread_mutex_t my_lock = PTHREAD_MUTEX_INITIALIZER; void *mythread(void *ptr) { long int i,j; while (1) { pthread_mutex_lock (&my_lock); for (i=0; i<10; i++) { printf ("Thread %d\n", int) ptr); for (j=0; j< ; j++); } pthread_mutex_unlock (&my_lock); for (j=0; j< ; j++); } int main (int argc, char *argv[]) { pthread_t thread[2]; pthread_create(&thread[0], NULL, mythread, (void *)0); pthread_create(&thread[1], NULL, mythread, (void *)1); getchar(); } 24Copyright ©: University of Illinois CS 241 Staff

Condition Variables Used to communicate information about the state of shared data  Execution of code depends on the state of A data structure or Another running thread Allows threads to synchronize based upon the actual value of data Without condition variables  Threads continually poll to check if the condition is met Copyright ©: University of Illinois CS 241 Staff25

Condition Variables Signaling, not mutual exclusion  A mutex is needed to synchronize access to the shared data Each condition variable is associated with a single mutex  Wait atomically unlocks the mutex and blocks the thread  Signal awakens a blocked thread Copyright ©: University of Illinois CS 241 Staff26

Creating a Condition Variable Similar to pthread mutexes int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); int pthread_cond_destroy(pthread_cond_t *cond); pthread_cond_t cond = PTHREAD_COND_INITIALIZER; Copyright ©: University of Illinois CS 241 Staff27

Using a Condition Variable Waiting  Block on a condition variable.  Called with mutex locked by the calling thread  Atomically release mutex and cause the calling thread to block on the condition variable  On return, mutex is locked again int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime); Copyright ©: University of Illinois CS 241 Staff28

Using a Condition Variable Signaling int pthread_cond_signal(pthread_cond_t *cond);  unblocks at least one of the blocked threads int pthread_cond_broadcast(pthread_cond_t *cond);  unblocks all of the blocked threads Signals are not saved  Must have a thread waiting for the signal or it will be lost Copyright ©: University of Illinois CS 241 Staff29

Condition Variable: Why do we need the mutex? pthread_mutex_lock(&mutex); /* lock mutex */ while (!predicate) { /* check predicate */ pthread_cond_wait(&condvar, &mutex); /* go to sleep – recheck pred on awakening */ } pthread_mutex_unlock(&mutex); /* unlock mutex */ pthread_mutex_lock(&mutex); /* lock the mutex */ predicate=1; /* set the predicate */ pthread_cond_broadcast(&condvar); /* wake everyone up */ pthread_mutex_unlock(&mutex); /* unlock the mutex */ Copyright ©: University of Illinois CS 241 Staff30

Condition Variable: No mutex! pthread_mutex_lock(&mutex); /* lock mutex */ while (!predicate) { /* check predicate */ pthread_mutex_unlock(&mutex); /* unlock mutex */ pthread_cond_wait(&condvar); /* go to sleep – recheck pred on awakening */ pthread_mutex_lock(&mutex); /* lock mutex */ } pthread_mutex_unlock(&mutex); /* unlock mutex */ pthread_mutex_lock(&mutex); /* lock the mutex */ predicate=1; /* set the predicate */ pthread_cond_broadcast(&condvar); /* wake everyone up */ pthread_mutex_unlock(&mutex); /* unlock the mutex */ Copyright ©: University of Illinois CS 241 Staff What can happen here? 31

Condition Variable: No mutex! pthread_mutex_lock(&mutex); /* lock mutex */ while (!predicate) { /* check predicate */ pthread_mutex_unlock(&mutex); /* unlock mutex */ pthread_cond_wait(&condvar); /* go to sleep – recheck pred on awakening */ pthread_mutex_lock(&mutex); /* lock mutex */ } pthread_mutex_unlock(&mutex); /* unlock mutex */ pthread_mutex_lock(&mutex); /* lock the mutex */ predicate=1; /* set the predicate */ pthread_cond_broadcast(&condvar); /* wake everyone up */ pthread_mutex_unlock(&mutex); /* unlock the mutex */ Copyright ©: University of Illinois CS 241 Staff32

Condition Variable: No mutex! pthread_mutex_lock(&mutex); /* lock mutex */ while (!predicate) { /* check predicate */ pthread_mutex_unlock(&mutex); /* unlock mutex */ pthread_cond_wait(&condvar); /* go to sleep – recheck pred on awakening */ pthread_mutex_lock(&mutex); /* lock mutex */ } pthread_mutex_unlock(&mutex); /* unlock mutex */ pthread_mutex_lock(&mutex); /* lock the mutex */ predicate=1; /* set the predicate */ pthread_cond_broadcast(&condvar); /* wake everyone up */ pthread_mutex_unlock(&mutex); /* unlock the mutex */ Copyright ©: University of Illinois CS 241 Staff The problem is here Another thread might acquire the mutex, set the predicate, and issue the broadcast before pthread_cond_wait() gets called 33

Condition Variable: We need the mutex! pthread_mutex_lock(&mutex); /* lock mutex */ while (!predicate) { /* check predicate */ pthread_cond_wait(&condvar, &mutex); /* go to sleep – recheck pred on awakening */ } pthread_mutex_unlock(&mutex); /* unlock mutex */ pthread_mutex_lock(&mutex); /* lock the mutex */ predicate=1; /* set the predicate */ pthread_cond_broadcast(&condvar); /* wake everyone up */ pthread_mutex_unlock(&mutex); /* unlock the mutex */ Copyright ©: University of Illinois CS 241 Staff34

Condition Variable: Why do we need the mutex? Separating the condition variable from the mutex  Thread goes to sleep when it shouldn't  Problem pthread_mutex_unlock() and pthread_cond_wait() are not guaranteed to be atomic Joining condition variable and mutex  Call to pthread_cond_wait() unlocks the mutex  UNIX kernel can guarantee that the calling thread will not miss the broadcast Copyright ©: University of Illinois CS 241 Staff35

Using a Condition Variable: Challenges Call pthread_cond_signal() before calling pthread_cond_wait()  Logical error – waiting thread will not catch the signal Fail to lock the mutex before calling pthread_cond_wait()  May cause it NOT to block Fail to unlock the mutex after calling pthread_cond_signal()  May not allow a matching pthread_cond_wait() routine to complete (it will remain blocked). Copyright ©: University of Illinois CS 241 Staff36

Example without Condition Variables int data_avail = 0; pthread_mutex_t data_mutex = PTHREAD_MUTEX_INITIALIZER; void *producer(void *) { pthread_mutex_lock(&data_mutex); data_avail=1; pthread_mutex_unlock(&data_mutex); } Copyright ©: University of Illinois CS 241 Staff37

Example without Condition Variables void *consumer(void *) { while( !data_avail ); /* do nothing */ pthread_mutex_lock(&data_mutex); if (queue is empty) data_avail = 0; pthread_mutex_unlock(&data_mutex); } Copyright ©: University of Illinois CS 241 Staff38 Busy Waiting!

Example with Condition Variables int data_avail = 0; pthread_mutex_t data_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cont_t data_cond = PTHREAD_COND_INITIALIZER; void *producer(void *) { pthread_mutex_lock(&data_mutex); data_avail = 1; pthread_cond_signal(&data_cond); pthread_mutex_unlock(&data_mutex); } Copyright ©: University of Illinois CS 241 Staff39

Example with Condition Variables void *consumer(void *) { pthread_mutex_lock(&data_mutex); while( !data_avail ) { /* sleep on condition variable*/ pthread_cond_wait(&data_cond, &data_mutex); } /* woken up */ if (queue is empty) data_avail = 0; pthread_mutex_unlock(&data_mutex); } Copyright ©: University of Illinois CS 241 Staff40 No Busy Waiting! Mutex solution while( !data_avail ); /* do nothing */

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 Staff41

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 Staff42

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 Staff43

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 Staff44 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 Staff45

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 Staff46

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 Staff47

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