views:

47

answers:

2

What are the different ways of ensuring that a bunch of pthreads all start at the same time?

I could find only one way, ie. initializing a barrier in the main thread, then waiting on it in the newly created pthreads.

+3  A: 

That's pretty much exactly how I've done it in the past.

main:
    claim mutex
    for each desired thread:
        start child
    release mutex
    :

child:
    claim mutex
    release mutex
    :

Note that this doesn't actually guarantee that all the threads have started before the first one starts doing something, just that the main thread has created them.

In order to do that, you can use something like the following method:

main:
    claim mutex
    set unstarted to 0
    for each desired thread:
        start child
        add 1 to unstarted
    release mutex
    :

child:
    claim mutex
    subtract 1 from unstarted
    while unstarted > 0:
        release mutex
        yield // if necessary
        claim mutex
    release mutex
    :

Whatever initialisation a thread has to do to be considered started will occur between the claim and the subtract.


I see from further investigation that barriers are actually a more elegant way to do this. They weren't actually available in the pthread implementations I used which is why my code may seem a little verbose.

However, I'll leave it as-is on the off-chance that someone uses pre-v6 pthreads or a different threading method (without barriers) and because, as the question asked, this is a different way of doing it.

paxdiablo
Do POSIX semaphores not work well with pthreads, or is there another reason not to use them?
Pete Kirkham
@Pete, no idea. I tend not to mix things like that since they always end up like sodium and water :-) In my opinion, if you're going to use pthreads, then _use_ them. Don't half-use them.
paxdiablo
@Pete, `sem_t` works well with POSIX threads, but they have several disadvantages. The first is that their `wait` is interruptible, so you have to be very careful when programming with this this. Then, starting threads simultaneously is not so easy with them: if you just use one semaphore the master thread has to do `N` individual post operations to launch the others. This is not what I would exactly call "launched simultaneously".
Jens Gustedt
+1  A: 

You can use pthread_cond_broadcast. They won't be launched completely simultaneously because of the mutex. You could try to use a different mutex for each thread, but using different mutexes for the same condition variable is undefined.

#include <pthread.h>

pthread_mutex_t join_mut = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void thread_function (void *param) {
    pthread_mutex_lock(&join_mut);
    pthread_cond_wait(&cond, &join_mut);
    pthread_mutex_unlock(&join_mut); 

    /* Thread work here */
}

enum { threads = 16 };

int main() {
  int i;
  pthread_t thread_table[threads];

  for(i = 0; i < threads; i++) {
    pthread_create(&(thread_table[i]), NULL, thread_function, NULL);
  }

  /* Wait for all threads to be queued */

  pthread_cond_broadcast(&cond);
}
Mathias Brossard