• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Linux 多线程编程实例

    一、多线程 VS 多进程

    和进程相比,线程有很多优势。在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护代码段和数据。而运行于一个进程中的多个线程,他们之间使用相同的地址空间。正是这样,同一进程下的线程之间共享数据空间,数据可以相互使用,并且线程间切换也要更快些,可以更有效的利用CPU。

    二、程序设计

    [注] 头文件pthread.h> 编译时要加载动态库 libpthread.a,使用 -lpthread
     
    1、创建线程
    2、等待线程
    3、关闭线程
    4、退出清除
     
    1、创建线程

    复制代码
    代码如下:

    int pthread_create(pthread_t *tidp, const pthread_attr_t *attr, void *(*start_rtn)(void), void *arg)

    tidp为线程id,是函数分配的值,所以要传一个 pthread_t 的地址。
    attr线程属性,通常为空。
    start_rtn为线程要执行的函数,返回值为空指针,参数为后面的*arg
    若成功则返回0,否则返回出错编号。
     
    例:


    复制代码
    代码如下:

    #includestdio.h>
    #includepthread.h>/p> p>void *func1(void *arg){ //原函数声明
    int i;
    for(i=0;i5;i++){
    printf("this is func1! The num is %d\n",*(int*)arg); //将空指针转换为int型指针
    sleep(1);
    }
    }/p> p>void *func2(int *m){ //自定义类型声明,也可以定义非指针类型,但是在create时会有警告,因为非地址并不能改变传入的值
    int i;
    for(i=0;i5;i++){
    printf("this is func2! The num is %d\n",*m);
    (*m)++;
    sleep(1);
    }
    }/p> p>int main(){
    pthread_t id1,id2;
    int num = 5;
    int *p = num;
    if(pthread_create(id1,NULL,(void *)func1,(void *)p) != 0){
    printf("thread1 create error!\n");
    return -1;
    }
    if(pthread_create(id2,NULL,(void *)func2,num) != 0){
    printf("thread2 create error!\n");
    return -1;
    }
    pthread_join(id1,NULL); //等待线程结束
    pthread_join(id2,NULL);
    printf("Running complete!\n");
    return 0;/p> p>
    }

    运行结果:


    复制代码
    代码如下:

    [fsy@localhost process]$ gcc thC.c -o thC -lpthread -g
    [fsy@localhost process]$ ./thC
    this is func2! The num is 5
    this is func1! The num is 6
    this is func2! The num is 6
    this is func1! The num is 7
    this is func2! The num is 7
    this is func1! The num is 8
    this is func2! The num is 8
    this is func1! The num is 9
    this is func2! The num is 9
    this is func1! The num is 10
    Running complete!
    [fsy@localhost process]$


    2、等待线程

    [注]当调用pthread_create函数时,线程并没有开始执行,主进程应有等待,比如用sleep,或者用更专业的函数:pthread_join

    复制代码
    代码如下:

    int pthread_join(pthread_t tid, void **rval_ptr)

    调用函数可以阻塞调用线程,直到指定的线程终止。
    tid为等待退出线程的id,rval_ptr为函数的返回值。是指向指针的指针,可以置空。
     
    例:

    复制代码
    代码如下:

    #includestdio.h>
    #includepthread.h>
    #includestdlib.h>/p> p>void *func(int *p){
    int *num=(int *)malloc(sizeof(int)); //必须动态创建,原因可以参考我动态分配内存的博客
    printf("Please input the number: ");
    scanf("%d",num);
    return (void *)num; //类型是pthread_create的参数规定的
    }/p> p>int main(){
    pthread_t pth;
    void *a;
    if(pthread_create(pth,NULL,(void *)func,NULL) != 0){
    printf("create thread error!\n");
    return 1;
    }
    pthread_join(pth,a); //指向空指针的指针
    printf("get the num from the thread, it's %d\n",*(int *)a);
    return 0;
    }

    3、终止线程

    线程终止有以下三种方式:

    1、线程从函数中返回
    2、线程可以别其他函数终止
    3、线程自己调用pthread_exit函数

    复制代码
    代码如下:

    void pthread_exit(void *rval_ptr)

    rval_ptr为线程退出返回值的指针,即函数返回值。

    4、退出清除

    复制代码
    代码如下:

    void pthread_cleanup_push(void (*rtn)(void*), void *arg)

    rtn为清除函数,arg是清除函数的参数

    复制代码
    代码如下:

    void pthread_cleanup_pop(int execute)

    当execute 非0时执行清除函数。为0时不执行。

    从pthread_cleanup_push的调用点到pthread_cleanup_pop之间的程序段中,如果有终止进程的动作,如调用pthread_exit或异常终止(不包括return),就会执行pthread_cleanup_push()所指定的清理函数。多个嵌套匹配时,就近匹配。
     
    例:

    复制代码
    代码如下:

    #includestdio.h>
    #includepthread.h>/p> p>void *clean(char *argv){
    printf("clean is called by %s\n",argv);
    return NULL;
    }
    void *func1(void *argv){
    printf("welcome enter the func1!\n");
    pthread_cleanup_push((void*)clean,"the first time call!");
    pthread_cleanup_push((void*)clean,"the second time call!");
    if(argv){
    return (void *)1; //第二次运行将此句注掉
    }
    pthread_cleanup_pop(0);
    pthread_cleanup_pop(1);
    return (void *)0;
    }/p> p>void *func2(void *argv){
    sleep(1); //两个线程运行先后不确定
    printf("welcome enter the func2!\n");
    pthread_cleanup_push((void*)clean,"the first time call!");
    pthread_cleanup_push((void*)clean,"the second time call!");
    if(argv){
    pthread_exit(NULL);
    }
    pthread_cleanup_pop(0);
    pthread_cleanup_pop(0);
    return (void *)0;
    }/p> p>
    int main(){
    pthread_t tid1,tid2;
    if(pthread_create(tid1,NULL,(void *)func1,(void *)1) != 0){
    printf("thread1 create error!\n");
    return 1;
    }/p> p> if(pthread_create(tid2,NULL,(void *)func2,(void *)1) != 0){
    printf("thread2 create error!\n");
    return 1;
    }
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    return 0;
    }

    运行结果:

    复制代码
    代码如下:

    [fsy@localhost process]$ gcc thClean.c -o thclean -lpthread
    [fsy@localhost process]$ ./thclean
    welcome enter the func1!
    welcome enter the func2!
    clean is called by the second time call! //此处先2后1
    clean is called by the first time call!
    [fsy@localhost process]$ vim thClean.c
    [fsy@localhost process]$ gcc thClean.c -o thclean -lpthread
    [fsy@localhost process]$ ./thclean
    welcome enter the func1!
    clean is called by the first time call! //second已经被pop
    welcome enter the func2!
    clean is called by the second time call!
    clean is called by the first time call!
    [fsy@localhost process]$

    上一篇:Linux消息队列编程示例
    下一篇:linux系统怎么重启网卡?linux重启网卡的三种教程
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    Linux 多线程编程实例 Linux,多,线程,编程,实例,