2015-09-04 62 views
0

为什么调用pthread_join(tid,& retval)的主函数不等待thread id等于tid的线程关闭?工作pthread_join(tid,&retval);

详细信息 - 我试图创建简单的多线程文件复制程序,以便我可以了解更多关于互斥锁,信号量和死锁,但不在主线程中使用sleep()的情况下,程序终止而不复制数据或不完整复制注意我在子线程中调用pthread_exit(retval)。

这里是代码 http://ideone.com/mexxmk 这里是一个运行无限计数器,以便检查子线程是否过早结束,即使在pthread_join被称为另一个代码。 http://ideone.com/0DIxUK ---结果:它不会过早结束。在后面的代码中,主线程会等待子线程关闭。 那么为什么第一个代码没有这样的行为。

+0

你叫pthread_detach( tid)或使用pthread_attr_setdetachedstate()以分离状态创建线程? –

+0

不,我不知道他们,我没有给他们打电话。我应该发布源代码吗? –

+0

是的,发布代码会很有帮助 - 谢谢。 –

回答

0

一种方法(即假设线程实际完成,其他可能的陷阱之中我还没有了解还)是使用一个互斥体,或东西沿着线:

#include <err.h> 
#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sysexits.h> 
#include <unistd.h> 

pthread_mutex_t Lock = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t Job_Done = PTHREAD_COND_INITIALIZER; 

unsigned long Threads_Completed; 

void *worker(void *unused); 

int main(void) 
{ 
    pthread_t *tids; 
    struct timespec wait; 

    if ((tids = calloc(sizeof(pthread_t), 42)) == NULL) 
     err(EX_OSERR, "could not calloc() threads list"); 

    fprintf(stderr, "dbg starting...\n"); 
    for (unsigned int i = 0; i < 42; i++) { 
     if (pthread_create(&tids[i], NULL, worker, NULL) != 0) 
      err(EX_OSERR, "could not pthread_create() thread %u", i); 
    } 

    wait.tv_sec = 7; 
    wait.tv_nsec = 0; 

    for (;;) { 
     pthread_mutex_lock(&Lock); 
     if (Threads_Completed == 42) 
      break; 
     pthread_cond_timedwait(&Job_Done, &Lock, &wait); 
     pthread_mutex_unlock(&Lock); 
    } 
    fprintf(stderr, "dbg all done!\n"); 

    exit(EXIT_SUCCESS); 
} 

void *worker(void *unused) 
{ 
    sleep(3 + rand() % 7);  // actual work here 
    fprintf(stderr, "dbg done!\n"); 

    pthread_mutex_lock(&Lock); 
    Threads_Completed++; 
    pthread_mutex_unlock(&Lock); 
    pthread_cond_signal(&Job_Done); 

    return (void *) 0; 
} 
+0

类似的东西可以工作,但是没有必要,因为pthread_join()会为你做。 pthread_join()不是问题。 –

+0

@VishvajeetPatil我支持我以前的建议。你试图一次编写和测试太多的代码。我建议你先从一个可用的pthread_create/pthread_join开始,然后逐渐添加---并测试---一次一小段代码。这将是找出问题的最简单方法。 –