Linux操作系统下的多线程编程详细解析

http://blog.csdn.net/ruglcc/article/details/7874076

zieckey zieckeyyahoo.com.cn

    
线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期,solaris是这方面的佼佼者。传统的Unix也支持线程的概念,但是在一个进程(process)中只允许有一个线程,这样多线程就意味着多进程。
现在,多线程技术已经被许多操作系统所支持,包括Windows/NT,当然,也包括Linux

  为什么有了进程的概念后,还要再引入线程呢?使用多线程到底有哪些好处?什么的系统应该选用多线程?我们首先必须回答这些问题。

  使用多线程的理由之一是和进程相比,它是一种非常"节俭"的多任务操作方式。我们知道,在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工作方式。而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。据统计,总的说来,一个进程的开销大约是一个线程开销的30倍左右,当然,在具体的系统上,这个数据可能会有较大的区别。

  使用多线程的理由之二是线程间方便的通信机制。对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便。线程则不然,由于同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。当然,数据的共享也带来其他一些问题,有的变量不能同时被两个线程所修改,有的子程序中声明为static的数据更有可能给多线程程序带来灾难性的打击,这些正是编写多线程程序时最需要注意的地方。

  除了以上所说的优点外,不和进程比较,多线程程序作为一种多任务、并发的工作方式,当然有以下的优点:

  1) 提高应用程序响应。这对图形界面的程序尤其有意义,当一个操作耗时很长时,整个系统都会等待这个操作,此时程序不会响应键盘、鼠标、菜单的操作,而使用多线程技术,将耗时长的操作(time consuming)置于一个新的线程,可以避免这种尴尬的情况。

  2) 使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。

  3) 改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。

  下面我们先来尝试编写一个简单的多线程程序。

  简单的多线程编程

  Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。顺便说一下,Linuxpthread的实现是通过系统调用clone()来实现的。clone()是Linux所特有的系统调用,它的使用方式类似fork,关于clone()的详细情况,有兴趣的读者可以去查看有关文档说明。下面我们展示一个最简单的多线程程序pthread_create.c


一个重要的线程创建函数原型:
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr, void *(*start_rtn)(void),void *restrict arg);

    
返回值:若是成功建立线程返回0,否则返回错误的编号
    
形式参数:
                pthread_t *restrict tidp 
要创建的线程的线程id指针
                const pthread_attr_t *restrict attr 
创建线程时的线程属性
                void* (start_rtn)(void) 
返回值是void类型的指针函数
                void *restrict arg   start_rtn
的行参
                
例程1                                
    
功能:创建一个简单的线程
    
程序名称:pthread_create.c         

  1. /******************************************************************************************** 
  2. **    Name:pthread_create.c 
  3. **    Used to study the multithread programming in Linux OS 
  4. **    Author:zeickey 
  5. **    Date:2006/9/16         
  6. **    Copyright (c) 2006,All Rights Reserved! 
  7. *********************************************************************************************/  
  8.   
  9. #include <stdio.h>  
  10. #include <pthread.h>  
  11.   
  12. void *myThread1(void)  
  13. {  
  14.     int i;  
  15.     for (i=0; i<100; i++)  
  16.     {  
  17.         printf("This is the 1st pthread,created by zieckey./n");  
  18.         sleep(1);//Let this thread to sleep 1 second,and then continue to run  
  19.     }  
  20. }  
  21.   
  22. void *myThread2(void)  
  23. {  
  24.     int i;  
  25.     for (i=0; i<100; i++)  
  26.     {  
  27.         printf("This is the 2st pthread,created by zieckey./n");  
  28.         sleep(1);  
  29.     }  
  30. }  
  31.   
  32. int main()  
  33. {  
  34.     int i=0, ret=0;  
  35.     pthread_t id1,id2;  
  36.       
  37.     ret = pthread_create(&id2, NULL, (void*)myThread1, NULL);  
  38.     if (ret)  
  39.     {  
  40.         printf("Create pthread error!/n");  
  41.         return 1;  
  42.     }  
  43.       
  44.     ret = pthread_create(&id2, NULL, (void*)myThread2, NULL);  
  45.     if (ret)  
  46.     {  
  47.         printf("Create pthread error!/n");  
  48.         return 1;  
  49.     }  
  50.       
  51.     pthread_join(id1, NULL);  
  52.     pthread_join(id2, NULL);  
  53.       
  54.     return 0;  
  55. }  



  我们编译此程序:
# gcc pthread_create.c -lpthread

因为pthread的库不是linux系统的库,所以在进行编译的时候要加上-lpthread,否则编译不过,会出现下面错误
thread_test.c: 
在函数 ‘create’ 中:
thread_test.c:7: 
警告: 在有返回值的函数中,程序流程到达函数尾
/tmp/ccOBJmuD.o: In function `main':thread_test.c:(.text+0x4f)
:对‘pthread_create’未定义的引用
collect2: ld 
返回 1

  运行,我们得到如下结果:
# ./a.out 
This is the 1st pthread,created by zieckey.
This is the 2st pthread,created by zieckey.
This is the 1st pthread,created by zieckey.
This is the 2st pthread,created by zieckey.
This is the 2st pthread,created by zieckey.
This is the 1st pthread,created by zieckey.
....

两个线程交替执行。
此例子介绍了创建线程的方法。
下面例子介绍向线程传递参数。


例程2
    
功能:向新的线程传递整形值
    
程序名称:pthread_int.c

  1. /******************************************************************************************** 
  2. **    Name:pthread_int.c 
  3. **    Used to study the multithread programming in Linux OS 
  4. **    Pass a parameter to the thread. 
  5. **    Author:zeickey 
  6. **    Date:2006/9/16         
  7. **    Copyright (c) 2006,All Rights Reserved! 
  8. *********************************************************************************************/  
  9.   
  10. #include <stdio.h>  
  11. #include <pthread.h>  
  12. #include <unistd.h>  
  13.   
  14. void *create(void *arg)  
  15. {  
  16.     int *num;  
  17.     num=(int *)arg;  
  18.     printf("create parameter is %d /n",*num);  
  19.     return (void *)0;  
  20. }  
  21. int main(int argc ,char *argv[])  
  22. {  
  23.     pthread_t tidp;  
  24.     int error;  
  25.       
  26.     int test=4;  
  27.     int *attr=&test;  
  28.       
  29.     error=pthread_create(&tidp,NULL,create,(void *)attr);  
  30.   
  31.     if(error)  
  32.         {  
  33.         printf("pthread_create is created is not created ... /n");  
  34.         return -1;  
  35.         }  
  36.     sleep(1);  
  37.     printf("pthread_create is created .../n");  
  38.     return 0;          
  39. }  



    编译方法:

gcc -lpthread pthread_int.c -Wall


    
执行结果:

create parameter is 4
pthread_create is created is  created ...


    
例程总结:
    
可以看出来,我们在main函数中传递的整行指针,传递到我们新建的线程函数中。
    
在上面的例子可以看出来我们向新的线程传入了另一个线程的int数据,线程之间还可以传递字符串或是更复杂的数据结构。


例程3
    
程序功能:向新建的线程传递字符串
        
程序名称:pthread_string.c

  1. /******************************************************************************************** 
  2. **    Name:pthread_string.c 
  3. **    Used to study the multithread programming in Linux OS 
  4. **    Pass a ‘char*‘ parameter to the thread. 
  5. **    Author:zeickey 
  6. **    Date:2006/9/16         
  7. **    Copyright (c) 2006,All Rights Reserved! 
  8. *********************************************************************************************/  
  9. #include <pthread.h>  
  10. #include <stdio.h>  
  11. #include <unistd.h>  
  12.   
  13. void *create(void *arg)  
  14. {  
  15.     char *name;  
  16.     name=(char *)arg;  
  17.     printf("The parameter passed from main function is %s  /n",name);  
  18.     return (void *)0;  
  19. }  
  20.   
  21. int main(int argc, char *argv[])  
  22. {  
  23.     char *a="zieckey";  
  24.     int error;  
  25.     pthread_t tidp;  
  26.   
  27.     error=pthread_create(&tidp, NULL, create, (void *)a);  
  28.   
  29.     if(error!=0)  
  30.     {  
  31.         printf("pthread is not created./n");  
  32.         return -1;  
  33.     }  
  34.     sleep(1);  
  35.     printf("pthread is created... /n");  
  36.     return 0;  
  37. }    


  
  编译方法:

gcc -Wall pthread_string.c -lpthread


    
执行结果:
The parameter passed from main function is zieckey  
pthread is created... 


    
例程总结:
    
可以看出来main函数中的字符串传入了新建的线程中。

例程4
    
程序功能:向新建的线程传递字符串
        
程序名称:pthread_struct.c

  1. /******************************************************************************************** 
  2. **    Name:pthread_struct.c 
  3. **    Used to study the multithread programming in Linux OS 
  4. **    Pass a ‘char*‘ parameter to the thread. 
  5. **    Author:zeickey 
  6. **    Date:2006/9/16         
  7. **    Copyright (c) 2006,All Rights Reserved! 
  8. *********************************************************************************************/  
  9. #include <stdio.h>  
  10. #include <pthread.h>  
  11. #include <unistd.h>  
  12. #include <stdlib.h>  
  13.   
  14. struct menber  
  15. {  
  16.     int a;  
  17.     char *s;  
  18. };  
  19.   
  20. void *create(void *arg)  
  21. {  
  22.     struct menber *temp;  
  23.     temp=(struct menber *)arg;  
  24.     printf("menber->a = %d  /n",temp->a);  
  25.     printf("menber->s = %s  /n",temp->s);  
  26.     return (void *)0;  
  27. }  
  28.   
  29. int main(int argc,char *argv[])  
  30. {  
  31.     pthread_t tidp;  
  32.     int error;  
  33.     struct menber *b;  
  34.     b=(struct menber *)malloc( sizeof(struct menber) );  
  35.     b->a = 4;  
  36.     b->s = "zieckey";  
  37.   
  38.     error = pthread_create(&tidp, NULL, create, (void *)b);  
  39.   
  40.     if( error )  
  41.     {  
  42.         printf("phread is not created.../n");  
  43.         return -1;  
  44.     }  
  45.     sleep(1);  
  46.     printf("pthread is created.../n");  
  47.     return 0;  
  48. }  




  编译方法:

gcc -Wall pthread_struct.c -lpthread


    
执行结果:
menber->a = 4  
menber->s = zieckey  
pthread is created...

    
例程总结:
    
可以看出来main函数中的一个结构体传入了新建的线程中。
    
线程包含了标识进程内执行环境必须的信息。他集成了进程中的所有信息都是对线程进行共享的,包括文本程序、程序的全局内存和堆内存、栈以及文件描述符。
    

例程5
    
程序目的:验证新建立的线程可以共享进程中的数据
    
程序名称:pthread_share.c  

  1. /******************************************************************************************** 
  2. **    Name:pthread_share_data.c 
  3. **    Used to study the multithread programming in Linux OS 
  4. **    Pass a ‘char*‘ parameter to the thread. 
  5. **    Author:zeickey 
  6. **    Date:2006/9/16         
  7. **    Copyright (c) 2006,All Rights Reserved! 
  8. *********************************************************************************************/  
  9. #include <stdio.h>  
  10. #include <pthread.h>  
  11. #include <unistd.h>  
  12.   
  13. static int a=4;  
  14. void *create(void *arg)  
  15. {  
  16.     printf("new pthread ... /n");  
  17.     printf("a=%d  /n",a);  
  18.     return (void *)0;  
  19. }  
  20.   
  21. int main(int argc,char *argv[])  
  22. {  
  23.     pthread_t tidp;  
  24.     int error;  
  25.       
  26.     a=5;  
  27.   
  28.     error=pthread_create(&tidp, NULL, create, NULL);  
  29.   
  30.     if(error!=0)  
  31.     {  
  32.         printf("new thread is not create ... /n");  
  33.         return -1;  
  34.     }  
  35.       
  36.     sleep(1);  
  37.       
  38.     printf("new thread is created ... /n");  
  39.     return 0;  
  40. }  


    
  编译方法:

gcc -Wall pthread_share_data.c -lpthread


    
执行结果:
new pthread ... 
a=5  
new thread is created ... 

    
例程总结:

可以看出来,我们在主线程更改了我们的全局变量a的值的时候,我们新建立的线程则打印出来了改变的值,可以看出可以访问线程所在进程中的数据信息

2、线程的终止

    
如果进程中任何一个线程中调用exit_Exit,或者是_exit,那么整个进程就会终止,
    
与此类似,如果信号的默认的动作是终止进程,那么,把该信号发送到线程会终止进程。
    
线程的正常退出的方式:
       (1) 
线程只是从启动例程中返回,返回值是线程中的退出码
       (2) 
线程可以被另一个进程进行终止
       (3) 
线程自己调用pthread_exit函数
    
两个重要的函数原型:

#include <pthread.h>
void pthread_exit(void *rval_ptr);
/*rval_ptr 
线程退出返回的指针*/

int pthread_join(pthread_t thread,void **rval_ptr);
   /*
成功结束进程为0,否则为错误编码*/


    
例程6
    
程序目的:线程正常退出,接受线程退出的返回码
    
程序名称:pthread_exit.c

  1. /******************************************************************************************** 
  2. **    Name:pthread_exit.c 
  3. **    Used to study the multithread programming in Linux OS 
  4. **    A example showing a thread to exit and with a return code. 
  5. **    Author:zeickey 
  6. **    Date:2006/9/16         
  7. **    Copyright (c) 2006,All Rights Reserved! 
  8. *********************************************************************************************/  
  9.   
  10. #include <stdio.h>  
  11. #include <pthread.h>  
  12. #include <unistd.h>  
  13.   
  14. void *create(void *arg)  
  15. {  
  16.     printf("new thread is created ... /n");  
  17.     return (void *)8;  
  18. }  
  19.   
  20. int main(int argc,char *argv[])  
  21. {  
  22.     pthread_t tid;  
  23.     int error;  
  24.     void *temp;  
  25.   
  26.     error = pthread_create(&tid, NULL, create, NULL);  
  27.   
  28.     if( error )  
  29.     {  
  30.         printf("thread is not created ... /n");  
  31.         return -1;  
  32.     }  
  33.     error = pthread_join(tid, &temp);  
  34.   
  35.     if( error )  
  36.     {  
  37.         printf("thread is not exit ... /n");  
  38.         return -2;  
  39.     }  
  40.       
  41.     printf("thread is exit code %d /n", (int )temp);  
  42.     return 0;  
  43. }  



  编译方法:

gcc -Wall pthread_exit.c -lpthread


    
执行结果:
new thread is created ...
thread is exit code 8

    
例程总结:
可以看出来,线程退出可以返回线程的int数值。线程退出不仅仅可以返回线程的int数值,还可以返回一个复杂的数据结构。

    
例程7
    
程序目的:线程结束返回一个复杂的数据结构
    
程序名称:pthread_return_struct.c

  1. #include <stdio.h>  
  2. #include <pthread.h>  
  3. #include <unistd.h>  
  4.   
  5. struct menber  
  6. {  
  7.     int a;  
  8.     char *b;  
  9. }temp={8,"zieckey"};  
  10. void *create(void *arg)  
  11. {  
  12.     printf("new thread ... /n");  
  13.     return (void *)&temp;  
  14. }  
  15.   
  16. int main(int argc,char *argv[])  
  17. {  
  18.     int error;  
  19.     pthread_t tid;  
  20.     struct menber *c;  
  21.   
  22.     error = pthread_create(&tid, NULL, create, NULL);  
  23.       
  24.     if( error )  
  25.     {  
  26.         printf("new thread is not created ... /n");  
  27.         return -1;  
  28.     }  
  29.     printf("main ... /n");  
  30.   
  31.     error = pthread_join(tid,(void *)&c);  
  32.   
  33.     if( error )  
  34.     {  
  35.         printf("new thread is not exit ... /n");  
  36.         return -2;  
  37.     }  
  38.     printf("c->a = %d  /n",c->a);  
  39.     printf("c->b = %s  /n",c->b);  
  40.     sleep(1);  
  41.     return 0;  
  42. }  



  编译方法:

gcc -Wall pthread_return_struct.c -lpthread


    
执行结果:

main ...
new thread ...
c->a = 8
c->b = zieckey


例程总结:
一定要记得返回的数据结构要是在这个数据要返回的结构没有释放的时候应用,如果数据结构已经发生变化,那返回的就不会是我们所需要的,而是脏数据

3、线程标识

    
函数原型:
   
#include <pthread.h>
pthread_t pthread_self(void);

pid_t getpid(void);
    getpid()
用来取得目前进程的进程识别码,函数说明

    
例程8
    
程序目的:实现在新建立的线程中打印该线程的id和进程id
    
程序名称:pthread_id.c
   

  1. /******************************************************************************************** 
  2. **    Name:pthread_id.c 
  3. **    Used to study the multithread programming in Linux OS. 
  4. **    Showing how to get the thread's tid and the process's pid. 
  5. **    Author:zeickey 
  6. **    Date:2006/9/16         
  7. **    Copyright (c) 2006,All Rights Reserved! 
  8. *********************************************************************************************/  
  9. #include <stdio.h>  
  10. #include <pthread.h>  
  11. #include <unistd.h> /*getpid()*/  
  12.   
  13. void *create(void *arg)  
  14. {  
  15.     printf("New thread .... /n");  
  16.     printf("This thread's id is %u  /n", (unsigned int)pthread_self());  
  17.     printf("The process pid is %d  /n",getpid());  
  18.     return (void *)0;  
  19. }   
  20.   
  21. int main(int argc,char *argv[])  
  22. {  
  23.     pthread_t tid;  
  24.     int error;  
  25.   
  26.     printf("Main thread is starting ... /n");  
  27.   
  28.     error = pthread_create(&tid, NULL, create, NULL);  
  29.   
  30.     if(error)  
  31.     {  
  32.         printf("thread is not created ... /n");  
  33.         return -1;  
  34.     }  
  35.     printf("The main process's pid is %d  /n",getpid());  
  36.     sleep(1);  
  37.     return 0;  
  38. }  




    编译方法:

   
gcc -Wall -lpthread pthread_id.c

    
执行结果:

Main thread is starting ... 
The main process's pid is 3307  
New thread .... 
This thread's id is 3086347152  
The process pid is 3307 


函数原型:

   #include <pthread.h>
void pthread_cleanup_push(void (*rtn)(void *),void *arg);
    
函数rtn是清理函数,arg是调用参数

void pthread_cleanup_pop(int execute);
  
    
在前面讲过线程的终止方式,是正常终止还是非正常终止,都会存在一个资源释放的问题,在posix中提供了一组,就是我们上面看的函数进行线程退出的处理函数,有些像在进程中的atexit函数。释放的方式是指pthread_cleanup_push的调用点到pthread_cleanup_pop之间程序段进行终止。

    pthread_cleanup_push()/pthread_cleanup_pop
采用先入后出的方式的栈的管理方式,void *rtn(void *),在执行pthread_cleanup_push()时压入函数栈,多次执行pthread_cleanup_push()形成一个函数链,在执行这个函数链的时候会以反方向弹出,即先入后出。execute参数表识,是否执行弹出清理函数,当execute=0时不进行弹出清理函数,非零的时候弹出处理函数。

    
例程9

    
程序目的:实现在正常结束线程的时候,进行函数处理

    
程序名称:pthread_clean.c

 

  1. /******************************************************************************************** 
  2. **    Name:pthread_clean.c 
  3. **    Used to study the multithread programming in Linux OS 
  4. **    A example showing a thread to be cleaned. 
  5. **    Author:zeickey 
  6. **    Date:2008/6/28         
  7. **    Copyright (c) 2006,All Rights Reserved! 
  8. *********************************************************************************************/  
  9. #include <stdio.h>  
  10. #include <pthread.h>  
  11. #include <unistd.h>  
  12. void *clean(void *arg)  
  13. {  
  14.     printf("cleanup :%s  /n",(char *)arg);  
  15.     return (void *)0;  
  16. }  
  17. void *thr_fn1(void *arg)  
  18. {  
  19.     printf("thread 1 start  /n");  
  20.     pthread_cleanup_push( (void*)clean,"thread 1 first handler");  
  21.     pthread_cleanup_push( (void*)clean,"thread 1 second hadler");  
  22.     printf("thread 1 push complete  /n");  
  23.     if(arg)  
  24.     {  
  25.         return((void *)1);  
  26.     }  
  27.     pthread_cleanup_pop(0);  
  28.     pthread_cleanup_pop(0);  
  29.     return (void *)1;  
  30. }  
  31. void *thr_fn2(void *arg)  
  32. {  
  33.     printf("thread 2 start  /n");  
  34.     pthread_cleanup_push( (void*)clean,"thread 2 first handler");  
  35.     pthread_cleanup_push( (void*)clean,"thread 2 second handler");  
  36.     printf("thread 2 push complete  /n");  
  37.     if(arg)  
  38.     {  
  39.         pthread_exit((void *)2);  
  40.     }  
  41.     pthread_cleanup_pop(0);  
  42.     pthread_cleanup_pop(0);  
  43.     pthread_exit((void *)2);  
  44. }  
  45. int main(void)  
  46. {  
  47.     int err;  
  48.     pthread_t tid1,tid2;  
  49.     void *tret;  
  50.   
  51.     err=pthread_create(&tid1,NULL,thr_fn1,(void *)1);  
  52.     if(err!=0)  
  53.     {  
  54.         printf("error .... /n");  
  55.         return -1;  
  56.     }  
  57.     err=pthread_create(&tid2,NULL,thr_fn2,(void *)1);  
  58.   
  59.     if(err!=0)  
  60.     {  
  61.         printf("error .... /n");  
  62.         return -1;  
  63.     }  
  64.     err=pthread_join(tid1,&tret);  
  65.     if(err!=0)  
  66.     {  
  67.         printf("error .... /n");  
  68.         return -1;  
  69.     }  
  70.     printf("thread 1 exit code %d  /n",(int)tret);  
  71.   
  72.     err=pthread_join(tid2,&tret);  
  73.     if(err!=0)  
  74.     {  
  75.         printf("error .... ");  
  76.         return -1;  
  77.     }  
  78.   
  79.     printf("thread 2 exit code %d  /n",(int)tret);  
  80.       
  81.     return 1;  
  82. }  



    编译方法:


 gcc -Wall -lpthread pthread_clean.c

    
执行结果:

thread 1 start  
thread 1 push complete  
thread 1 exit code 1  
thread 2 start  
thread 2 push complete  
cleanup :thread 2 second handler  
cleanup :thread 2 first handler  
thread 2 exit code 2 

pthread_join
   
SYNOPSIS
       #include <pthread.h>


       int pthread_join(pthread_t thread, void **rval_ptr);


DESCRIPTION
       The  pthread_join()  function shall suspend execution of the calling thread until the target thread terminates, unless the target thread has already termi-nated. On return from a successful pthread_join() call with a non-NULL value_ptr argument, the value passed to pthread_exit()  by  the  terminating  thread shall  be  made  available  in the location referenced by rval_ptr. When a pthread_join() returns successfully, the target thread has been terminated. The results of multiple simultaneous calls to pthread_join() specifying the same target thread are undefined. If the thread calling pthread_join() is canceled, then the target thread shall not be detached.
pthread_join用于挂起当前线程(调用pthread_join的线程),直到thread指定的线程终止运行为止,当前线程才继续执行。thread指定的线程的返回值由rval_ptr返回。一个线程所使用的资源在对该线程调用pthread_join之前不会被重新分配,因此对于每个切入的线程必须调用一次pthread_join函数。线程必须可切入的而不是处于被分离状态,并且其他线程不能对同一线程再次应用pthread_join调用。通过pthread_create调用中使用一个适当的attr参数或者调用pthread_detach可以让一个线程处于被分离状态。




   
SYNOPSIS
       #include <pthread.h>


       int pthread_join(pthread_t thread, void **rval_ptr);


DESCRIPTION
       The  pthread_join()  function shall suspend execution of the calling thread until the target thread terminates, unless the target thread has already termi-nated. On return from a successful pthread_join() call with a non-NULL value_ptr argument, the value passed to pthread_exit()  by  the  terminating  thread shall  be  made  available  in the location referenced by rval_ptr. When a pthread_join() returns successfully, the target thread has been terminated. The results of multiple simultaneous calls to pthread_join() specifying the same target thread are undefined. If the thread calling pthread_join() is canceled, then the target thread shall not be detached.
pthread_join用于挂起当前线程(调用pthread_join的线程),直到thread指定的线程终止运行为止,当前线程才继续执行。thread指定的线程的返回值由rval_ptr返回。一个线程所使用的资源在对该线程调用pthread_join之前不会被重新分配,因此对于每个切入的线程必须调用一次pthread_join函数。线程必须可切入的而不是处于被分离状态,并且其他线程不能对同一线程再次应用pthread_join调用。通过pthread_create调用中使用一个适当的attr参数或者调用pthread_detach可以让一个线程处于被分离状态。

  1. /******************************************************************************************** 
  2. **    Name:pthread_join.c 
  3. **    Used to study the multithread programming in Linux OS 
  4. **    A example showing a thread to be waited to end. 
  5. **    Author:zeickey 
  6. **    Date:2008/6/28         
  7. **    Copyright (c) 2006,All Rights Reserved! 
  8. *********************************************************************************************/  
  9.   
  10. #include <pthread.h>  
  11. #include <unistd.h>  
  12. #include <stdio.h>  
  13. void *thread(void *str)  
  14. {  
  15.     int i;  
  16.     for (i = 0; i < 10; ++i)  
  17.     {  
  18.         sleep(2);  
  19.         printf( "This in the thread : %d/n" , i );  
  20.     }  
  21.     return NULL;  
  22. }  
  23.   
  24. int main()  
  25. {  
  26.     pthread_t pth;  
  27.     int i;  
  28.     int ret = pthread_create(&pth, NULL, thread, (void *)(i));  
  29.       
  30.     pthread_join(pth, NULL);  
  31.     for (i = 0; i < 10; ++i)  
  32.     {  
  33.         sleep(1);  
  34.         printf( "This in the main : %d/n" , i );  
  35.     }  
  36.       
  37.     return 0;  
  38. }  


"pthread_join(pth, NULL);"这一行注释掉:
[root@localhost src]# gcc pthread_join.c -lpthread
[root@localhost src]# ./a.out
This in the main : 0
This in the thread : 0
This in the main : 1
This in the main : 2
This in the thread : 1
This in the main : 3
This in the main : 4
This in the thread : 2
This in the main : 5
This in the main : 6
This in the thread : 3
This in the main : 7
This in the main : 8
This in the thread : 4
This in the main : 9


子线程还没有执行完毕,main函数已经退出,那么子线程也就退出了。


“pthread_join(pth, NULL);”起作用
[root@localhost src]# gcc pthread_join.c -lpthread
[root@localhost src]# ./a.out
This in the thread : 0
This in the thread : 1
This in the thread : 2
This in the thread : 3
This in the thread : 4
This in the thread : 5
This in the thread : 6
This in the thread : 7
This in the thread : 8
This in the thread : 9
This in the main : 0
This in the main : 1
This in the main : 2
This in the main : 3
This in the main : 4
This in the main : 5
This in the main : 6
This in the main : 7
This in the main : 8
This in the main : 9
[root@localhost src]#


这说明pthread_join函数的调用者在等待子线程退出后才继续执行

posted @ 2013-05-10 09:32  ArcherDev  阅读(406)  评论(0编辑  收藏  举报