160 likes | 409 Views
Condition Variables. A condition variable is used to wait until a particular condition is true like in a monitor Always use condition variables together with a mutex lock The mutex provides the mutual exclusive aspect of a monitor
E N D
Condition Variables • A condition variable is used to wait until a particular condition is true • like in a monitor • Always use condition variables together with a mutex lock • The mutex provides the mutual exclusive aspect of a monitor • The attributes for condition variables must be set and initialized before the condition variables can be used
Steps in using a condition variable • Create an attribute object • Create a condition variable, associating it with an existing mutex • Use the condition variable • wait, signal, broadcast • 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 • If the object is not destroyed, a memory leak will result
Setting The Scope int pthread_condattr_setpshared( pthread_condattr_t*cattr, intpshared); • 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 • 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); • The pthread_cond_destroy() function destroys a previously initialized condition variable • The condition variable must not be used after it has been destroyed. • The space for storing the condition variable is not freed.
condvar.c #include <pthread.h> #include <iostream> 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 • You should use the g++ form of complier invocation • You must link with the pthread library • g++ mycode.cpp -lpthread • If you don’t include the link option, only your main thread will execute! • This works with Solaris; details vary from system to system