我不确定以下代码是否会导致未定义的行为。
//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。规范解决方案,是否有一个互斥计数器来跟踪当前正在运行的线程数?
感谢
答案 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);
}