为当前运行的线程重用pthread_t变量

时间:2011-06-24 11:37:26

标签: c pthreads

我不确定以下代码是否会导致未定义的行为。

//global
pthread_t thread1;

void *worker(void *arg){
  //do stuff
}


void spawnThread(){
  //init stuff
  int iret1 = pthread_create( &thread1, NULL, worker, (void*) p);
}

我的spawnThread将使用全局thread1创建一个新线程。

如果我当前正在运行未完成的线程,在使用thread1变量启动新线程时,是否会以某种方式导致未定义的行为?

如果这是一个问题,将pthread_t变量设为函数本地是否有意义?我认为这可能是问题,因为它将使用堆栈,并且一旦我从我的函数返回将被删除。

如果我将pthread_t本地化为函数,我不能在程序的另一部分使用pthread_join。规范解决方案,是否有一个互斥计数器来跟踪当前正在运行的线程数?

感谢

3 个答案:

答案 0 :(得分:15)

pthread_t只是一个标识符。您可以将其复制或随意销毁。当然,正如你所提到的,如果你销毁它(因为它是本地的),那么你就不能用它来调用pthread_join

如果为多个线程重复使用相同的pthread_t变量,那么除非一次只激活一个线程,否则您将使用新值覆盖旧值,并且只能调用{{1在最近启动的线程上。此外,如果从多个线程内部启动线程,则需要使用互斥锁保护pthread_join变量。

如果您需要等待线程完成,请为其提供自己的pthread_t变量,并在需要等待的位置调用pthread_t。如果您不需要等待线程完成,请在创建后调用pthread_join,或使用创建属性启动分离的线程。

答案 1 :(得分:2)

pthread_t只是一个标识符,你可以用它做任何你喜欢的事情。线程状态在C库内部维护(在Glibc / NPTL的情况下,在线程本地存储上的内部struct thread上,通过GS寄存器在x86上访问)。

答案 2 :(得分:1)

问题是,你的 thread1 变量是引用你的第一个线程的唯一方法。

我经常使用的解决方案是有一个pthread_t数组,用于存储我需要引用的线程ID。在这个例子中,它是一个静态数组,但你也可以使用动态分配的内存。

static pthread_t running_threads[MAX_THREAD_RUNNING_LIMIT];
static unsigned int running_thread_count = 0;

// each time you create a new thread:
pthread_create( &running_threads[running_thread_count], blabla...);
running_thread_count++;

// don't forget to check running_thread_count against the size 
// of your running thread size MAX_THREAD_RUNNING_LIMIT

当你需要加入()时,只需循环执行:

for(i =0; i<running_thread_count; i++)
{
    pthread_join(&running_threads[i], &return_value);
}