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

5 篇文章 0 订阅
5 篇文章 0 订阅
线程( 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 。顺便说一下, Linux pthread 的实现是通过系统调用 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          
[cpp]  view plain copy
  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
[cpp]  view plain copy
  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
[cpp]  view plain copy
  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
[cpp]  view plain copy
  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  

[cpp]  view plain copy
  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

[cpp]  view plain copy
  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
[cpp]  view plain copy
  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
   
[cpp]  view plain copy
  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

 
[cpp]  view plain copy
  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可以让一个线程处于被分离状态。

[cpp]  view plain copy
  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函数的调用者在等待子线程退出后才继续执行
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Linux多线程服务端编程是指使用Muduo C网络库在Linux操作系统进行多线程的服务端编程。Muduo C网络库是一个基于事件驱动的网络库,采用了Reactor模式,并且在底层使用了epoll来实现高效的I/O复用。 使用Muduo C网络库进行多线程服务端编程有以下几个步骤: 1. 引入Muduo C网络库:首先需要下载并引入Muduo C网络库的源代码,然后在编写代码时包含相应的头文件。 2. 创建并初始化EventLoop:首先需要创建一个EventLoop对象,它用于接收和分发事件。通过初始化函数进行初始化,并在主线程调用它的loop()函数来运行事件循环。 3. 创建TcpServer:然后创建一个TcpServer对象,它负责监听客户端的连接,并管理多个TcpConnection对象。通过设置回调函数,可以在特定事件发生时处理相应的逻辑。 4. 创建多个EventLoopThread:为了提高并发性能,可以创建多个EventLoopThread对象,每个对象负责一个EventLoop,从而实现多线程处理客户端的连接和请求。 5. 处理事件:在回调函数处理特定事件,例如有新的连接到来时会调用onConnection()函数,可以在该函数进行一些初始化操作。当有数据到来时会调用onMessage()函数,可以在该函数处理接收和发送数据的逻辑。 6. 运行服务端:在主线程调用TcpServer的start()函数来运行服务端,等待客户端的连接和请求。 总的来说,使用Muduo C网络库进行Linux多线程服务端编程可以更好地利用多核处理器的性能优势。每个线程负责处理特定事件,通过事件驱动模式实现高效的网络编程。这样可以提高服务器的并发能力,提高系统的整体性能。 ### 回答2: Linux多线程服务端编程是指在Linux平台上使用多线程的方式来编写网络服务器程序。而使用muduo C网络库是一种常见的方法,它提供了高效的网络编程接口,可以简化多线程服务器的开发过程。 muduo C网络库基于Reactor模式,利用多线程实现了高并发的网络通信。在使用muduo C进行多线程服务端编程时,我们可以按照以下步骤进行: 1. 引入muduo库:首先需要导入muduo C网络库的头文件,并链接对应的库文件,以供程序调用。 2. 创建线程池:利用muduo C的ThreadPool类创建一个线程池,用于管理和调度处理网络请求的多个线程。 3. 创建TcpServer对象:使用muduo C的TcpServer类创建一个服务器对象,监听指定的端口,并设置好Acceptor、TcpConnectionCallback等相关回调函数。 4. 定义业务逻辑:根据具体的业务需求,编写处理网络请求的业务逻辑代码,如接收客户端的请求、处理请求、发送响应等。 5. 注册业务逻辑函数:将定义好的业务逻辑函数注册到TcpServer对象,以便在处理网络请求时调用。 6. 启动服务器:调用TcpServer对象的start函数,启动服务器,开始监听端口并接收客户端请求。 7. 处理网络请求:当有客户端连接到服务器时,muduo C会自动分配一个线程去处理该连接,执行注册的业务逻辑函数来处理网络请求。 8. 释放资源:在程序结束时,需要调用相应的函数来释放使用的资源,如关闭服务器、销毁线程池等。 通过使用muduo C网络库,我们可以简化多线程服务端编程的过程,提高服务器的并发处理能力。因为muduo C网络库已经实现了底层的网络通信细节,我们只需要专注于编写业务逻辑代码,从而减少开发的工作量。同时,muduo C的多线程模型可以有效地提高服务器的并发性能,满足高并发网络服务的需求。 ### 回答3: Linux多线程服务端编程是指在Linux操作系统上开发多线程的服务器应用程序。使用muduo C网络库有助于简化开发过程,提供高效的网络通信能力。 muduo C网络库是一个基于Reactor模式的网络库,适用于C++语言,由Douglas Schmidt的ACE网络库演化而来。它提供了高度并发的网络编程能力,封装了许多底层细节,使得开发者能够更加专注于业务逻辑的实现。 在开发过程,首先需要创建一个muduo C的EventLoop对象来管理事件循环。然后,可以利用TcpServer类来创建服务器并监听指定的端口。当有新的客户端请求到达时,muduo C会自动调用用户定义的回调函数处理请求。 在处理请求时,可以使用muduo C提供的ThreadPool来创建多个工作线程。这些工作线程将负责处理具体的业务逻辑。通过将工作任务分配给不同的线程,可以充分利用多核服务器的计算资源,提高服务器的处理能力。 在具体的业务逻辑,可以使用muduo C提供的Buffer类来处理网络数据。Buffer类提供了高效的数据读写操作,可以方便地进行数据解析与封装。 此外,muduo C还提供了TimerQueue类来处理定时任务,可以用于实现定时事件的调度与管理。这对于一些需要定期执行的任务非常有用,如心跳检测、定时备份等。 总之,使用muduo C网络库可以简化Linux多线程服务端编程的开发过程,提供高效的并发能力。通过合理地利用多线程和其他的相关组件,可以实现高性能、稳定可靠的网络服务端应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值