views:

203

answers:

3

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?

+5  A: 

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.

bdonlan
Oops, yea it should be pthread_cond_wait.
Edward Amsden
+1  A: 

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.

Bastien Léonard
A: 

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.

Tyler McHenry
Strictly speaking, SCHED_FIFO or SCHED_RR with a static priority higher than the writer threads, on a uniprocessor system would work. But on SMP you could still race for the lock.
bdonlan