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 with a mutex lock The mutex provides the mutual exclusive aspect of a monitor u The attributes for condition variables must be set and initialized before the condition variables can be used
Steps in using a condition variable u Create an attribute object u Create a condition variable, associating it with an existing mutex u Use the condition variable wait, signal, broadcast u Destroy the condition variable
Attribute Initialization int threads_condattr_init( pthread_condattr_t *cattr); The pthread_condattr_init() call returns a pointer to an opaque object The possible values of cattr’s scope are PTHREAD_PROCESS_PRIVATE (the default) and PTHREAD_PROCESS_SHARED u If the object is not destroyed, a memory leak will result
Setting The Scope int pthread_condattr_setpshared( pthread_condattr_t *cattr, int pshared); pthread_condattr_setpshared( ) sets the scope of a condition variable to either process private(intraprocess) or system wide (interprocess) pshared = PTHREAD_PROCESS_SHARED can be shared among threads from more than one process pshared = PTHREAD_PROCESS_PRIVATE only threads in the same process can operate on the object
Attribute Destruction int pthread_condattr_destroy( pthread_condattr_t *cattr); Use pthread_condattr_destroy( ) to remove storage and render the object invalid u The object must be reinitialized before it can be reused
Initialize A Condition Variable int pthread_cond_init( pthread_cond_t *cv, const pthread_condattr_t *cattr); Initializes the condition variable pointed at by cv to its default value (cattr = NULL) specify condition variable attributes that are already set with pthread_condattr_init()
Wait On Condition Variable int pthread_cond_wait( pthread_cond_t *cv, pthread_mutex_t *mp); Use pthread_cond_wait( ) to release the mutex pointed to by mp and to cause the calling thread to block on the condition variable pointed to by cv The blocked thread can be awakened by pthread_cond_signal() pthread_cond_broadcast()
Unblock A Thread int pthread_cond_signal( pthread_cond_t *cv); Use pthread_cond_signal( ) to unblock one thread that is blocked on the condition variable pointed to by cv If more than one thread is blocked on a condition variable, the scheduling policy determines the order in which blocked threads are awakened. For SCHED_OTHER, threads are awakened in priority order
Unblock All Threads Int pthread_cond_broadcast( pthread_cond_t *cv); Use pthread_cond_broadcast() to unblock all threads that are blocked on the condition variable pointed to by cv, specified by pthread_cond_wait() When no threads are blocked on the condition variable, pthread_cond_broadcast() has no effect
Destroy Condition Variable int pthread_cond_destroy( pthread_cond_t *cv); u The pthread_cond_destroy() function destroys a previously initialized condition variable u The condition variable must not be used after it has been destroyed. u The space for storing the condition variable is not freed.
condvar.c #include using namespace std; const int t = 5; const int MAX = 2000; const int MAX_COUNT = t*MAX; int counter = 0; pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t count_max = PTHREAD_COND_INITIALIZER; int thread_id[t+1];
condvar.c (continued) void* watch(void* ID) { int* id = (int*)ID; pthread_mutex_lock(&count_mutex); cout << "The watch has begun." << endl; while(counter < MAX_COUNT) pthread_cond_wait(&count_max,&count_mutex); cout << "The value is "<< counter<< "######"<< endl; pthread_mutex_unlock(&count_mutex); return NULL; }
condvar.c (continued) void* increment(void* ID) { int *id = (int*)ID; int i; for(i=0; i< MAX ; i++) { pthread_mutex_lock(&count_mutex); counter++; cout<<"id: "<<*id<<" i: "<<i<<" counter: " <<counter<< endl; if (counter == MAX_COUNT) pthread_cond_signal(&count_max); pthread_mutex_unlock(&count_mutex); } return NULL; }
condvar.c int main(int argc, char *argv[]) { pthread_attr_t myATTR; pthread_attr_init (&myATTR); pthread_attr_setscope(&myATTR, PTHREAD_SCOPE_SYSTEM); for(int i=0;i<t+1;i++) thread_id[i]=i; pthread_t thread[t+1]; pthread_create(&thread[t], &myATTR, watch, (void*)&thread_id[t]); for(int i=0; i<t;i++) pthread_create(&thread[i], &myATTR, increment, (void*)&thread_id[i]); for(int i=0; i<= t ; i++) pthread_join(thread[i], NULL); return 0; }
Compiling your C++ code with pthreads u You should use the g++ form of complier invocation u You must link with the pthread library g++ mycode.cpp -lpthread u If you don’t include the link option, only your main thread will execute! u This works with Solaris; details vary from system to system