我可以用什么来等待创建所有线程?

时间:2018-05-28 19:11:04

标签: c multithreading unix pthreads

如果我想在main中创建5个新线程并等待在开始工作之前创建所有这五个线程,我应该使用什么?

我找到了pthread_cond_wait,也许这就是我应该使用的,但我不确定如何。有没有办法知道线程是否已创建,而不是立即进入该线程?

感谢。

1 个答案:

答案 0 :(得分:2)

我认为您所描述的内容并不是一个好主意:您如何管理由于某些错误而未创建线程的情况?

pthread_cond_wait可能是一个优雅的解决方案,但你应该为5个线程中的每一个使用等待条件;加上条件更像是一个触发器:当事情发生时,做一些事情。从你所描述的,你想要的东西更像是一个初始条件。

一个简单的解决方案是使用一个全局变量作为计数器,每次创建5个线程中的一个,计数器就会递增:

无论如何,要查看线程是否正确创建,您可以使用以下内容:

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

然后在每个线程函数中,使用一个什么也不做的循环,其循环条件检查计数器变量是否小于你想要创建的线程数:

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

注意:这很危险,因为如果你在选择变量值时不小心,你就会遇到5个无限循环。

此外,您应该使用某种类型的互斥锁(可能是读/写互斥锁),因为全局计数器由一个线程写入并由许多线程读取。

重要编辑:此外,您应该在未创建其中一个线程时管理这种情况(例如,杀死已创建的线程而不创建其他线程),否则其他线程将再次陷入其中无限循环。

编辑2

我知道这是很久以前的问题,但实际上也有其他解决方案,也许更优雅。

一个是你的问题中使用pthread_cond_wait()在线程中的一个,它必须等待初始化线程中的初始化和pthread_cond_broadcoast() / pthread_cond_signal()

pthread_cond_signalpthread_cond_broadcast之间的区别如下:在前者中,单个线程将获取锁并执行。其他人仍然需要等待。使用pthread_cond_broadcast,所有线程将同时解除阻塞。例如:

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);
}

我认为另一种解决方案是使用写锁定和写锁定:在开始时main thread在写入时锁定读写互斥锁。其他线程会尝试将其锁定(例如,如果你想同时将它们唤醒,则在读取模式下)但是有一个写锁定它们将被阻止。

创建所有线程后,main解锁,其他线程可以执行:

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);
}