zoukankan      html  css  js  c++  java
  • linux c编程:线程退出

    在线程创建的时候pthread_exit都是调用的固定参数,我们先来看下如果用自动变量作为pthread_exit的参数时出现的问题

    typedef struct foo{

        int a;

        int b;

        int c;

        int d;

    }foo;

    void printinfo(const char *s,const struct foo *fp){

        printf("%s",s);

        printf("structure at 0x%lx ",(unsigned long)fp);

        printf("foo.a=%d ",fp->a);

        printf("foo.b=%d ",fp->b);

        printf("foo.c=%d ",fp->c);

        printf("foo.d=%d ",fp->d);

    }

    void printids(const char *s){

        pid_t pid;

        pthread_t tid;

        pid=getpid();

        tid=pthread_self();

        printf("%s pid %lu tid %lu (0x%lx) ",s,(unsigned long)pid,(unsigned long)tid,(unsigned long)tid);

    }

    void *thr_fn2(void *arg){

        printf("threaqd 2:ID is %lu ",(unsigned long)pthread_self());

        pthread_exit((void *)0);

    }

    void *thr_fn1(void *arg){

        foo f={1,2,3,4};

        printinfo("thread1: ",&f);

        pthread_exit((void *)&f);

    }

    int main()

    {

        pthread_t tid1,tid2;

        foo *fp;

        pthread_create(&tid1,NULL,thr_fn1,NULL);

        pthread_join(tid1,(void *)&fp);

        Sleep(1);

        printf("parent starting create thread2: ");

        pthread_create(&tid2,NULL,thr_fn2,NULL);

        Sleep(1);

        printinfo("parent: ",fp);

        return 0;

    }

    在这个程序中,调用pthread_join(tid1,(void *)&fp)的时候会将返回码赋值给fp参数。然后再父进程中调用fp。

    执行结果:可以看到当父进程中试图访问已退出的第一个线程传给它的结构时,内存不在有效,因此得到了SIGSEGV信号

    Thread1:

    Structure at 0x2bfff04

    foo.a=1

    foo.b=2

    foo.c=3

    foo.d=4

    parent starting create thread2

    thread 2 : ID is 3

    segmentation fault(core dumped)

    线程可以安排它退出时需要调用的函数,这样的函数称为线程清理处理程序。

    void thread_cleanup_push(void (*rtn)(void *), void *arg);

    void pthread_cleanup_pop(int execute)

    rtn是调用的函数,arg是传入的参数。

    void cleanup(void *arg){

        printf("cleanup:%s ",(char *)arg);

    }

    void *thr_fn2(void *arg){

        printf("thread2 start ");

        pthread_cleanup_push(cleanup,"thread2 first handler");

        pthread_cleanup_push(cleanup,"thread2 second handler");

        printf("thread2 push complete ");

        if (arg)

            pthread_exit((void *)2);

        pthread_cleanup_pop(0);

        pthread_cleanup_pop(0);

    }

    void *thr_fn1(void *arg){

        printf("thread1 start ");

        pthread_cleanup_push(cleanup,"thread1 first handler");

        pthread_cleanup_push(cleanup,"thread1 second handler");

        printf("thread1 push complete ");

        if (arg)

            return((void *)1);

        pthread_cleanup_pop(0);

        pthread_cleanup_pop(0);

    }

    int main()

    {

        pthread_t tid1,tid2;

        void *tret;

        pthread_create(&tid1,NULL,thr_fn1,(void *)1);

        pthread_create(&tid2,NULL,thr_fn2,(void *)1);

        pthread_join(tid1,&tret);

        printf("thread 1 exit code %ld ",(long)tret);

        pthread_join(tid2,&tret);

        printf("thread 2 exit code %ld ",(long)tret);

        return 0;

    }

    运行结果如下:两个线程都正确的自动启动和退出了,但是只有第二个线程的清理处理程序被调用了,如果线程是通过从它的启动历程中返回(return)而不是pthread_exit的话,它的清理程序就不会调用

  • 相关阅读:
    java IO流详解
    java设计模式之单例模式(几种写法及比较)
    JS定时刷新页面及跳转页面
    遍历map的四种方法
    String 中去掉空格
    TSP问题_遗传算法(STL大量使用)
    无向图的深度优先生成树和广度优先生成树
    Prim算法求最小生成树
    哈夫曼编码_静态库
    中序线索化二叉树
  • 原文地址:https://www.cnblogs.com/zhanghongfeng/p/9280181.html
Copyright © 2011-2022 走看看