70 likes | 243 Views
Chapter 30 Condition Variables. Chien -Chung Shen CIS, UD cshen@cis.udel.edu. Basic Ideas. A thread check whether a condition is true before continuing (parent waits for child) void *child(void * arg ) { printf ("child<br>") ; / / XXX how to indicate we are done? return NULL; }
E N D
Chapter 30Condition Variables Chien-Chung Shen CIS, UD cshen@cis.udel.edu
Basic Ideas • A thread check whether a condition is true before continuing (parent waits for child) void *child(void *arg) { printf("child\n"); // XXX how to indicate we are done? return NULL; } main(intargc, char *argv[]) {printf("parent: begin\n");pthread_tc;Pthread_create(&c, NULL, child, NULL); // create child // XXX how to wait for child? printf("parent: end\n"); return 0; }
How to Wait for a Condition ? • “Shared” (global) variable volatile int done = 0; void *child(void *arg) { printf("child\n"); done = 1; return NULL; } main(intargc, char *argv[]) {printf("parent: begin\n");pthread_t c;Pthread_create(&c, NULL, child, NULL); // create child while (done == 0) ; // spin printf("parent: end\n"); return 0; } • Drawback • spin and waste CPU time
How to Wait for a Condition ? • Condition variable • idea: some way to put the parent to sleep until the condition we are waiting for (e.g., the child is done executing) comes true • an explicit queuethat threads can put themselves on when some state of execution is notas desired (by waiting on the condition) • some other thread, when it changes said state, wake one (or more) of those waiting threads and allow them to continue
Pthread Wait • pthread_cond_wait(&c, &m) • release the lock (m) and put the calling thread to sleep (atomically) • when the thread wakes up (after some other thread has signaled it), it must reacquire the lock (m) before returning to the caller • prevent race condition when a thread is trying to put itself to sleep
Pthread Condition Variable int done = 0;pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t c = PTHREAD_COND_INITIALIZER; void thr_exit() { Pthread_mutex_lock(&m); done = 1; Pthread_cond_signal(&c); Pthread_mutex_unlock(&m); } void *child(void *arg) { printf("child\n"); thr_exit();return NULL; } void thr_join() { Pthread_mutex_lock(&m); while(done == 0) Pthread_cond_wait(&c, &m); // release m when sleeping (atomically) // reacquire m when wake up Pthread_mutex_unlock(&m); } main(intargc, char *argv[]) { printf("parent: begin\n");pthread_tp; Pthread_create(&p, NULL, child, NULL); thr_join(); printf("parent: end\n"); return 0; }
Will the Following Work ? void thr_exit() { Pthread_mutex_lock(&m) Pthread_cond_signal(&c); Pthread_mutex_unlock(&m); } • Do we need done? • failed when child runs immediately and calls thr_exit() void thr_exit(){ done = 1; Pthread_cond_signal(&c); } • Does not hold a lock when wait and signal? • Failed when parent proceeds first (and will sleep forever) void thr_join() { Pthread_mutex_lock(&m); Pthread_cond_wait(&c, &m); Pthread_mutex_unlock(&m); } void thr_join() { if (done == 0) Pthread_cond_wait(&c); } interrupt