Use condition variables to atomically block threads until a particular condition is true. Always use condition variables together with a mutex lock.
With a condition variable, a thread can atomically block until a condition is satisfied. The condition is tested under the protection of a mutual exclusion lock (mutex).
When the condition is false, a thread usually blocks on a condition variable and atomically releases the mutex waiting for the condition to change. When another thread changes the condition, it can signal the associated condition variable to cause one or more waiting threads to wake up, acquire the mutex again, and reevaluate the condition.
Condition variables can be used to synchronize threads among processes when they are allocated in memory that can be written to and is shared by the cooperating processes.
The scheduling policy determines how blocking threads are awakened. For the default SCHED_OTHER, threads are awakened in priority order.
The attributes for condition variables must be set and initialized before the condition variables can be used. The functions that manipulate condition variable attributes are listed in Table 4-4.
Table 4-4 Condition Variable Attributes
Operation |
Destination Discussion | |
---|---|---|
Initialize a condition variable attribute | ||
Remove a condition variable attribute | ||
Set the scope of a condition variable | ||
Get the scope of a condition variable |
The differences between Solaris and POSIX threads, when defining the scope of a condition variable, are shown in Table 4-5.
Table 4-5 Condition Variable Scope Comparison
Solaris |
POSIX |
Definition |
---|---|---|
USYNC_PROCESS |
PTHREAD_PROCESS_SHARED |
Use to synchronize threads in this and other processes |
USYNC_THREAD |
PTHREAD_PROCESS_PRIVATE |
Use to synchronize threads in this process only |
Use pthread_condattr_init(3THR) to initialize attributes associated with this object to their default values. Storage for each attribute object is allocated by the threads system during execution. The default value of the pshared attribute when this function is called is PTHREAD_PROCESS_PRIVATE, which means that the initialized condition variable can be used within a process.
Prototype: int pthread_condattr_init(pthread_condattr_t *cattr);
#include <pthread.h> pthread_condattr_t cattr; int ret; /* initialize an attribute to default value */ ret = pthread_condattr_init(&cattr);
cattr is an opaque data type that contains a system-allocated attribute object. The possible values of cattr's scope are PTHREAD_PROCESS_PRIVATE (the default) and PTHREAD_PROCESS_SHARED.
Before a condition variable attribute can be reused, it must first be reinitialized by pthread_condattr_destroy(3T). The pthread_condattr_init() call returns a pointer to an opaque object. If the object is not destroyed, a memory leak will result.
pthread_condattr_init() returns zero after completing successfully. Any other returned value indicates that an error occurred. When either of the following conditions occurs, the function fails and returns the corresponding value.
There is not enough memory to initialize the thread attributes object.
The value specified by cattr is invalid.
Use pthread_condattr_destroy(3THR) to remove storage and render the attribute object invalid.
Prototype: int pthread_condattr_destroy(pthread_condattr_t *cattr);
#include <pthread.h> pthread_condattr_t cattr; int ret; /* destroy an attribute */ ret = pthread_condattr_destroy(&cattr);
pthread_condattr_destroy() returns zero after completing successfully. Any other returned value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
pthread_condattr_setpshared(3THR) sets the scope of a condition variable to either process private (intraprocess) or system wide (interprocess). If the condition variable is created with the pshared attribute set to the PTHREAD_PROCESS_SHARED state, and it exists in shared memory, it can be shared among threads from more than one process. This is equivalent to the USYNC_PROCESS flag in mutex_init() in the original Solaris threads.
If the mutex pshared attribute is set to PTHREAD_PROCESS_PRIVATE (default value), only those threads created by the same process can operate on the mutex. Using PTHREAD_PROCESS_PRIVATE results in the same behavior as with the USYNC_THREAD flag in the original Solaris threads cond_init() call, which is that of a local condition variable. PTHREAD_PROCESS_SHARED is equivalent to a global condition variable.
Prototype: int pthread_condattr_setpshared(pthread_condattr_t *cattr, int pshared);
#include <pthread.h> pthread_condattr_t cattr; int ret; /* all processes */ ret = pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED); /* within a process */ ret = pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_PRIVATE);
pthread_condattr_setpshared() returns zero after completing successfully. Any other returned value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
pthread_condattr_getpshared(3THR) gets the current value of pshared for the attribute object cattr. The value is either PTHREAD_PROCESS_SHARED or PTHREAD_PROCESS_PRIVATE.
Prototype: int pthread_condattr_getpshared(const pthread_condattr_t *cattr, int *pshared);
#include <pthread.h> pthread_condattr_t cattr; int pshared; int ret; /* get pshared value of condition variable */ ret = pthread_condattr_getpshared(&cattr, &pshared);
pthread_condattr_getpshared() returns zero after completing successfully. Any other returned value indicates that an error occurred. When the following condition occurs, the function fails and returns the corresponding value.