pthread_join pthread_exit pthread_detach

pthread_join     pthread_exit  
  
函数pthread_join用来等待一个线程的结束。函数原型为:
  extern int pthread_join __P ((pthread_t __th, void
**__thread_return));
 
 第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。这个函数是一个线程阻塞的函数,调用它的函数将
一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。一个线程的结束有两种途径,一种是象我们上面的例子一样,函数结束了,调用它的
线程也就结束了;另一种方式是通过函数pthread_exit来实现。它的函数原型为:
  extern void pthread_exit __P ((void *__retval)) __attribute__
((__noreturn__));
 
 唯一的参数是函数的返回代码,只要pthread_join中的第二个参数thread_return不是NULL,这个值将被传递给
thread_return。最后要说明的是,一个线程不能被多个线程等待,否则第一个接收到信号的线程成功返回,其余调用pthread_join的线程则返回错误代码ESRCH。


int pthread_detach( pthread_t pid );

//参数tid 是希望等待的线程的线程号, 把指定的线程转变为脱离状态
一个线程或者是可汇合的(joinable,缺省值),或者是脱离的(detached)。当一个可汇合的线程终止时,它的线程ID和退出状态将留到另一个线程对它调用pthread_join。脱离线程却象守护进程:当它们终止的时,所有相关资源都被释放,我们不能等待它们终止。如果一个线程需要知道另一个线程什么时候终止,那就最好使第二个线程的可汇合状态。

下面 通过例子说明:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

#define THREAD_NUMBER 2
int retval_hello1= 1, retval_hello2 = 2;

void* hello1(void *arg)
{   
   char *hello_str = (char *)arg;
   sleep(2);
   printf("%s/n", hello_str);
   pthread_exit(&retval_hello1);
}

void* hello2(void *arg)
{
   char *hello_str = (char *)arg;
   sleep(1);
   printf("%s/n", hello_str);
   pthread_exit(&retval_hello2);
}

int main(int argc, char *argv[])
{
   int i;
   int ret_val;
   int *retval_hello[2];
  
   pthread_t pt[THREAD_NUMBER];
   const char *arg[THREAD_NUMBER];
   arg[0] = "hello world from thread1";
   arg[1] = "hello world from thread2";
  
   printf("Begin to create threads.../n");
   ret_val = pthread_create(&pt[0], NULL, hello1, (void *)arg[0]);
   if (ret_val != 0 ) {
      printf("pthread_create error!/n");
      exit(1);
   }

   ret_val = pthread_create(&pt[1], NULL, hello2, (void *)arg[1]);
   if (ret_val != 0 ) {
      printf("pthread_create error!/n");
      exit(1);
   }
  
   printf("Begin to wait for threads.../n");  
   for(i = 0; i < THREAD_NUMBER; i++) {
       ret_val = pthread_join(pt[i], (void **)&retval_hello[i]);
       if (ret_val != 0) {
          printf("pthread_join error!/n");
      exit(1);
       } else {
          printf("return value is %d/n", *retval_hello[i]);
       }
   }
   printf("Now, the main thread returns./n");
   return 0;
}

执行结果为:

Begin to create threads...
Begin to wait for threads...
hello world from thread2
hello world from thread1
return value is 1
return value is 2
Now, the main thread returns.

线程1,2的执行顺序可以通过sleep来调节,但是主线程必须在子线程完成之后才能执行,即打印”Now, the main thread returns.“。此外,因为调用pthread_join()的顺序,必定是线程1先执行“return value is xx”,不管线程2是否先执行完。

下面修改pthread_join为pthread_detach(),代码为

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

#define THREAD_NUMBER 2
int retval_hello1= 1, retval_hello2 = 2;

void* hello1(void *arg)
{   
   char *hello_str = (char *)arg;
   sleep(2);
   printf("%s/n", hello_str);
   pthread_exit(&retval_hello1);
}

void* hello2(void *arg)
{
   char *hello_str = (char *)arg;
   sleep(1);
   printf("%s/n", hello_str);
   pthread_exit(&retval_hello2);
}

int main(int argc, char *argv[])
{
   int i;
   int ret_val;
   int *retval_hello[2];
  
   pthread_t pt[THREAD_NUMBER];
   const char *arg[THREAD_NUMBER];
   arg[0] = "hello world from thread1";
   arg[1] = "hello world from thread2";
  
   printf("Begin to create threads.../n");
   ret_val = pthread_create(&pt[0], NULL, hello1, (void *)arg[0]);
   if (ret_val != 0 ) {
      printf("pthread_create error!/n");
      exit(1);
   }

   ret_val = pthread_create(&pt[1], NULL, hello2, (void *)arg[1]);
   if (ret_val != 0 ) {
      printf("pthread_create error!/n");
      exit(1);
   }
  
   printf("Begin to wait for threads.../n");  
   for(i = 0; i < THREAD_NUMBER; i++) {
       ret_val = pthread_detach(pt[i]);
       if (ret_val != 0) {
          printf("pthread_join error!/n");
      exit(1);
       }
   }
   printf("Now, the main thread returns./n");
   return 0;
}

执行结果为

Begin to create threads...
Begin to wait for threads...
Now, the main thread returns.
线程1,2没有执行(也可能执行),因为子线程为可分离的,主线程在执行完之后即将进程销毁,资源收回,导致子线程未运行。可以在return 0 语句之前加入sleep(5),这样执行结果为

Begin to create threads...
Begin to wait for threads...
Now, the main thread returns.
hello world from thread2
hello world from thread1
所以,pthread_join()会挂起父线程,直至子线程完成才可以执行后面的代码,此外,一个PTHREAD_CREATE_JOINABLE状态的子线程不会自动释放该线程的内存资源,包括线程描述符和其使用的栈;而主线程调用pthread_detach()时,无需等待子线程的完成,它可以立即执行后面的代码,当然,也有可能主线程执行完之后销毁进程,导致子线程未能执行,此外,一个PTHREAD_CREATE_DETACH状态的子线程拥有自我回收内存资源的功能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值