Assuming I have a C program with 3 POSIX threads, sharing a global variable, mutex, and condition variable, two of which are executing the following psuedocode:
...process data...
pthread_mutex_lock( &mutex );
variable = data_ptr;
pthread_cond_signal( &cond );
pthread_mutex_unlock( &mutex );
And the third running:
while(1) {
while( variable == NULL ) {
pthread_mutex_wait( &cond, &mutex );
}
printf( "Data is %d", *variable );
}
Is it safe to assume that the third thread will see the data from each of the first two?
Put a different way, if a thread is wating on a mutex and a condition variable, is it safe to assume that it will be the next one to get the lock if it is signaled, rather than some other thread that may be waiting on the lock?
There's no such thing as pthread_mutex_wait. I assume you mean:
pthread_mutex_lock(&mutex);
/* ... */
while (1) {
while (variable == NULL)
pthread_cond_wait(&cond, &mutex);
printf("Data is %d", *variable);
}
/* ... */
pthread_mutex_unlock(&mutex);
There is no guarentee that the third thread will see the data from both. pthread_cond_signal will awaken the third thread, but it may not take the mutex immediately. One of the other writers may take the mutex first. However you can acheive what you want with a bit more work:
void put(int *p) {
pthread_mutex_lock(&mutex);
while (variable)
pthread_cond_wait(&cond_empty, &mutex);
variable = p;
pthread_cond_signal(&cond_full);
pthread_mutex_unlock(&mutex);
}
int *get() {
int *ret;
pthread_mutex_lock(&mutex);
while (!variable)
pthread_cond_wait(&cond_full, &mutex);
ret = variable;
variable = NULL;
pthread_cond_signal(&cond_empty);
pthread_mutex_unlock(&mutex);
return ret;
}
By explicitly waiting for the variable to be read, we avoid the potential race condition.
Here is what I found in the standard:
4.13 Scheduling Policy
A scheduling policy affects process or thread ordering:
[...]
- When a process or thread is a blocked thread and it becomes a runnable thread
Conforming implementations shall define the manner in which each of the scheduling policies may modify the priorities or otherwise affect the ordering of processes or threads at each of the occurrences listed above. Additionally, conforming implementations shall define in what other circumstances and in what manner each scheduling policy may modify the priorities or affect the ordering of processes or threads.
So it's apparently undefined. It's not surprising: generally speaking, you can't assume anything about which runnable thread will be scheduled to run.
According to the pthread_cond_wait
manpage
The thread(s) that are unblocked shall contend for the mutex according to the scheduling policy (if applicable), and as if each had called pthread_mutex_lock
().
Unfortunately as far as I can tell, there is no available scheduling policy that gives you the behavior you want.