zoukankan      html  css  js  c++  java
  • 线程分离

    pthread_detach函数

    实现线程分离

           int pthread_detach(pthread_t thread);      成功:0;失败:错误号

           线程分离状态:指定该状态,线程主动与主控线程断开关系。线程结束后,其退出状态不由其他线程获取,而直接自己自动释放。网络、多线程服务器常用。

           进程若有该机制,将不会产生僵尸进程。僵尸进程的产生主要由于进程死后,大部分资源被释放,一点残留资源仍存于系统中,导致内核认为该进程仍存在。

           也可使用 pthread_create函数参2(线程属性)来设置线程分离。

    【练习】:使用pthread_detach函数实现线程分离                                                                      【pthrd_detach.c】

    一般情况下,线程终止后,其终止状态一直保留到其它线程调用pthread_join获取它的状态为止。但是线程也可以被置为detach状态,这样的线程一旦终止就立刻回收它占用的所有资源,而不保留终止状态。不能对一个已经处于detach状态的线程调用pthread_join,这样的调用将返回EINVAL错误。也就是说,如果已经对一个线程调用了pthread_detach就不能再调用pthread_join了。

    /***
    detach.c
    ***/
    #include<unistd.h>
    #include<string.h>
    #include<pthread.h>
    #include<stdio.h>
    
    void *tfn(void *arg)
    {
        int n = 3;
        while(n--)
        {
            printf("thread count %d
    ",n);
            sleep(1);
        }
        pthread_exit((void*)1);
    }
    
    int main()
    {
        pthread_t tid;
        void* tret;
        int err;
    
        pthread_attr_t attr;
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
        pthread_create(&tid,&attr,tfn,NULL);
    
        while(1)
        {
            err = pthread_join(tid,&tret);
            printf("------------------- err = %d
    ",err);
            if(0 != err)
            {
                fprintf(stderr,"thread_join error : %s
    ",strerror(err));
            }
            else
            {
                fprintf(stderr,"thread exit code %d
    ",(int)tret);
            }
            sleep(1);
        }
    
        return 0;
    }

    运行结果:

    ubuntu1604@ubuntu:~/wangqinghe/linux/20190819$ ./detach

    ------------------- err = 22

    thread_join error : Invalid argument

    thread count 2

    ------------------- err = 22

    thread_join error : Invalid argument

    thread count 1

    ------------------- err = 22

    thread_join error : Invalid argument

    thread count 0

    ------------------- err = 22

    thread_join error : Invalid argument

    ------------------- err = 22

    thread_join error : Invalid argument

    ------------------- err = 22

    thread_join error : Invalid argument

    ------------------- err = 22

    thread_join error : Invalid argument

    ^C

    pthread_cancel函数

    杀死(取消)线程                  其作用,对应进程中 kill() 函数。

           int pthread_cancel(pthread_t thread); 成功:0;失败:错误号

           【注意】:线程的取消并不是实时的,而有一定的延时。需要等待线程到达某个取消点(检查点)。

           类似于玩游戏存档,必须到达指定的场所(存档点,如:客栈、仓库、城里等)才能存储进度。杀死线程也不是立刻就能完成,必须要到达取消点。

           取消点:是线程检查是否被取消,并按请求进行动作的一个位置。通常是一些系统调用creat,open,pause,close,read,write..... 执行命令man 7 pthreads可以查看具备这些取消点的系统调用列表。也可参阅 APUE.12.7 取消选项小节。

    可粗略认为一个系统调用(进入内核)即为一个取消点。如线程中没有取消点,可以通过调用pthreestcancel函数自行设置一个取消点。

    被取消的线程,   退出值定义在Linux的pthread库中。常数PTHREAD_CANCELED的值是-1。可在头文件pthread.h中找到它的定义:#define PTHREAD_CANCELED ((void *) -1)。因此当我们对一个已经被取消的线程使用pthread_join回收时,得到的返回值为-1。

    【练习】:终止线程的三种方法。注意“取消点”的概念。                                                              【pthrd_endof3.c】

    终止线程方式

    总结:终止某个线程而不终止整个进程,有三种方法:

    1. 从线程主函数return。这种方法对主控线程不适用,从main函数return相当于调用exit。
    2. 一个线程可以调用pthread_cancel终止同一进程中的另一个线程。
    3. 线程可以调用pthread_exit终止自己
    /***
    pthread_endof3.c
    ***/
    
    #include <stdio.h>
    #include <unistd.h>
    #include <pthread.h>
    #include <stdlib.h>
    
    
    void *tfn1(void *arg)
    {
        printf("thread 1 returning
    ");
    
        return (void *)111; 
    }
    
    void *tfn2(void *arg)
    {
        printf("thread 2 exiting
    ");
        pthread_exit((void *)222);
    }
    
    void *tfn3(void *arg)
    {
        while (1) {
            //printf("thread 3: I'm going to die in 3 seconds ...
    ");
            //sleep(1);
    
            pthread_testcancel();    //自己添加取消点*/
        }
    
        return (void *)666;
    }
    
    int main(void)
    {
        pthread_t tid;
        void *tret = NULL;
    
        pthread_create(&tid, NULL, tfn1, NULL);
        pthread_join(tid, &tret);
        printf("thread 1 exit code = %d
    
    ", (int)tret);
    
        pthread_create(&tid, NULL, tfn2, NULL);
        pthread_join(tid, &tret);
        printf("thread 2 exit code = %d
    
    ", (int)tret);
    
        pthread_create(&tid, NULL, tfn3, NULL);
        sleep(3);
        pthread_cancel(tid);
        pthread_join(tid, &tret);
        printf("thread 3 exit code = %d
    ", (int)tret);
    
        return 0;
    }

    ubuntu1604@ubuntu:~/wangqinghe/linux/20190819$ ./pthread_endof3

    thread 1 returning

    thread 1 exit code = 111

    thread 2 exiting

    thread 2 exit code = 222

    thread 3 exit code = -1

  • 相关阅读:
    页面高度自适应方法(PC、移动端都适用)
    Axure 文本框去掉边框 富文本 粘贴文字图标
    Axure 文本框去掉边框 富文本 粘贴文字图标
    mui switch 点击事件不冒泡
    使用vue-router+vuex进行导航守卫(转)
    Layui select下拉框改变之 change 监听事件(转)
    jQuery获取节点和子节点文本的方法
    动态规划(3)——算法导论(18)
    动态规划(2)——算法导论(17)
    Base64编码
  • 原文地址:https://www.cnblogs.com/wanghao-boke/p/11389738.html
Copyright © 2011-2022 走看看