tethys4
tethys4

Reputation: 55

What can I use to wait for all threads to be created?

If I wanted to create 5 new threads in main and wait for all five of those threads to be created before starting the work in them, what should I use?

I found pthread_cond_wait and maybe that is what I should be using but I am not really sure how. Is there any way to know a thread was created and not go into that thread immediately?

Thanks.

Upvotes: 1

Views: 530

Answers (1)

roschach
roschach

Reputation: 9336

I do not think it is a good idea what you described: how would you manage the situation where a thread is not created due to some errors?

pthread_cond_wait is maybe an elegant solution but you should use a wait condition for each of the 5 threads; plus a condition is more like a trigger: when something happens, do something. From what you have described you want something that is more like an initial condition.

One simple solution is to use a global variable which is a counter and everytime one of the 5 threads is created, the counter is incremented:

Anyway, to see if a thread is created correctly you can use something like this:

if ((err = pthread_create (&threadID, NULL, threadFunction, NULL))!=0)
{
    printf("some error\n");
}
else
{
    global_counter++;
}

Then in each of the thread functions, use a loop that does nothing and whose loop condition checks if the counter variable is less than the number of threads you want to create:

while (global_counter<5)
{
    ;
}
..../rest of the thread functions

NOTE: it is dangerous because if you are not careful in choosing the variable values you get stuck in 5 infinite loops.

Also you should use some type of mutex (read/write mutex maybe) since the global counter is written by one thread and read by many.

IMPORTANT EDIT: Also you should manage the situation when one of the threads is not created (for example killing the already created threads and not creating the others) otherwise the others will be stuck again in that infinite loop.

EDIT 2

I know this was asked a long time ago but actually there are also other solutions, maybe more elegant.

One is the one sited in your question using pthread_cond_wait() in the thread that must wait for an initialization and pthread_cond_broadcoast()/pthread_cond_signal() in the initialization thread.

The difference between pthread_cond_signal and pthread_cond_broadcast is the following: in the former a single thread will acquire the lock and execute. The others still have to wait. With pthread_cond_broadcast all threads will be unblocked simultaneously. For example:

pthread_mutex_t mtx;
pthread_cond_t  cv;

void* threadFunction(void*);

int main()
{
  pthread_mutex_lock(&mtx);
  for (int i=0; i<5; i++)
  {
    if ((err = pthread_create (&threadID, NULL, threadFunction, NULL))!=0)
    {
       printf("some error\n");
    }
  }
  pthread_cond_broadcast(&cv);
  pthread_mutex_unlock(&mtx);
}

void* threadFunction(void*)
{
  pthread_mutex_lock(&mtx);
  pthread_cond_wait(&cv, &mtx);
  do_things();
  pthread_mutex_unlock(&mtx);
}

Another solution in my opinion is to use write-lock and write lock: at the beginning the main thread lock a read-write mutex on write. Other threads will try it to lock it (for example in read mode if you want to wake them up simultaneously) but there being a write lock they will be blocked.

When all threads are created the main unlock and the others can execute:

pthread_rwlock_t lock; 

void* threadFunction(void*);

int main()
{
  pthread_rwlock_init(&lock, ...);
  //First acquire the write lock:
  if ((res = pthread_rwlock_wrlock(&lock)!=0)
  {
      exit(1);
  } 
  for (int i=0; i<5; i++)
  {
    if ((err = pthread_create (&threadID, NULL, threadFunction, NULL))!=0)
    {
       printf("some error\n");
    }
  }
  pthread_rwlock_unlock(&lock);
  pthread_rwlock_destroy(&lock);
  }

void* threadFunction(void*)
{
  pthread_rwlock_rdlock(&lock);
  do_things();
  pthread_rwlock_unlock(&lock);
}

Upvotes: 2

Related Questions