linux pthread 状态和pthread终止

主要想说明两个问题:线程的两种类型( 状态):join和detach,还有就是线程函数中pthread_exit和return的区别.
1.join和detach.  
join:线程A创建线程B(C,D.....)后,若A需要等待线程B的结果,或者说需要AB需要同步.或者说A需要等待B的结果.这时join状态.创建线程时,默认的是join状态.同一进程下的线程都是peer,可以是其他线程等待join B,不只是A.只有join后,才会释放资源.
detach:线程A创建线程B后,对A来说,好了,我的任务结束了,B自己玩去吧.A不需要等待B的结果,或者说不需要等待B结束的时候.这时就是detach状态.和join对比,线程执行完成后,自动释放资源.
这两种状态的选择实际上是看需求上的设计.例如,自己获取linux本机信息,cpu,mem,disk,net时,需要开4线程收集信息,等到都收集完成后,再汇总.需要等待4个线程的返回.设计使用join.


int pthread_join(pthread_t thread,void **rval_ptr) //二级指针
(顺便说下APUE第二版294页上代码
err=pthread_join(tid1,(void *)&fp); // void这里貌似应该是(void **)
)
看下手册上和APUE上的说明:
1.等待特定的线程返回,如果线程还在运行,阻塞等待,如果已经执行完成,立即返回
2.返回的指针拷贝的目标线程的退出时的指针(一级指针)值.如果目标线程被取消掉,返回PTHREAD_CANCELED.
返回值可以通过return (void*)ptr 或者pthread_exit((void*)ptr)从线程中返回.由join接收.
3.多个线程同时join一个线程时,结果未定义.可能出错.不要多次在不同的线程调用join同一个线程.
4.如果pthread_join被取消掉,线程依然是可以join状态.
5.对于可join的线程,线程返回后并没有释放资源,而是等待join后才释放的资源.
6.join之前已经join过的线程的是没有定义的.可能会有异常情况
7.一个进程中的所有线程都是peer,任何线程可以join到其他线程中去.
8.join线程失败,将会产生僵尸线程.
9.线程中没有像进程函数waitpid(-1,&status,0)//-1为接收任何进程.可以接收任何线程的函数,即必须指明pthread_t
10.对分离状态的线程即detach状态,则会返回错误.


线程变成detach状态有两种方式:
1.函数:int pthread_detach(pthead_t tid);


2.线程属性设置.
在线程创建的时候,create函数,有属性变量.
pthread_attr_setdetachstate(&attr,PTHREAD_DETACHED);
分离状态的线程,只是在运行完之后,自动释放资源.当进程(主线程)return或者exit时,分离状态的线程依然会被终止.


pthread_join和pthread_detach只有被创建线程函数的线程中调用,才会被释放资源.
在手册上给出了一个有意思的例子.

pthread_detach(pthread_self());待验证


最后在手册上pthread_detach上:

pthread_join和pthread_detach应该由创建线程的线程调用,才会释放资源,当然,在所有线程结束后,所有资源都会被释放.



2.return 和pthread_exit

return和pthread_exit的区别:“理论上说,pthread_exit()和线程宿体函数退出的功能是相同的,函数结束时会在内部自动调用pthread_exit()来清理线程相关的资源。但实际上二者由于编译器的处理有很大的不同。在进程主函数(main())中调用pthread_exit(),只会使主函数所在的线程(可以说是进程的主线程)退出;而如果是return,编译器将使其调用进程退出的代码(如_exit()),从而导致进程及其所有线程结束运行。”

所以呢,在宿体函数内是没有区别的(理论上);但是在宿主函数内,return将结束进程

pthread_exit()用于线程退出,可以指定返回值,以便其他线程通过pthread_join()函数获取该线程的返回值

return,是函数返回,不一定是线程函数哦! 只有线程函数return,线程才会退出

exit()是进程退出,如果在线程函数中调用exit,那改线程的进程也就挂了,会导致该线程所在进程的其他线程也挂掉.

在线程中(非主线程),调用return时 ,会隐式调用pthread_exit.


两者具体不同搜了一下:大概的意思是:

pthrad_exit可能会导致内存泄露,dopen库文件,但是并没有dclose,原因是可能会被其他用到.

使用return的话就不会出现这种情形.使用的检测软件是:valgrind.

自己测试了一下,现在pthread_exit并没有出现可能的内存泄露.搜到的信息有点旧了.

测试环境:valgrind-3.7.0 内核:3.5.0-23-generic

测试c和c++两种.结果都是没有内存泄露了.

代码:

C

#include 
#include 
#include 
#include 
#include 

void *app1(void *x) 
{
    printf("in thread\n");
    pthread_exit(0);
}

int main()
{
    pthread_t t1; 

    pthread_create(&t1, NULL, app1, NULL);
    pthread_join(t1, NULL);

    return 0;
}

c++代码也差不多.

另外一个例子:这个是传递的主函数 栈里的指针(地址).

#include 
#include 

using namespace std;

struct taskdata
{
       int  x;
     float  y;
    string  z;
};


void* task1(void *data)
{
    taskdata *t = (taskdata *) data;

    t->x += 25;
    t->y -= 4.5;
    t->z = "Goodbye";

    return(data);
}

void* task2(void *data)
{
    taskdata *t = (taskdata *) data;

    t->x -= 25;
    t->y += 4.5;
    t->z = "World";

    pthread_exit(data);
}


int main(int argc, char *argv[])
{
    pthread_t threadID;

    taskdata t = {10, 10.0, "Hello"};

    void *status;

    cout << "before " << t.x << " " << t.y << " " << t.z << endl;

    //by return()

    pthread_create(&threadID, NULL, task1, (void *) &t);

    pthread_join(threadID, &status);

    taskdata *ts = (taskdata *) status;

    cout << "after task1 " << ts->x << " " << ts->y << " " << ts->z << endl;

    //by pthread_exit()

    pthread_create(&threadID, NULL, task2, (void *) &t);

    pthread_join(threadID, &status);

    ts = (taskdata *) status;

    cout << "after task2 " << ts->x << " " << ts->y << " " << ts->z << endl;

}
函数结束后,栈里的内容被释放,return/pthread_exit,怎么传递的参数.网上说,return和pthread_exit将参数放在能被pthread_join的地方.


pthread_exit和return还有一个区别是:

如果线程是从启动例程中返回(return)终止的话,线程清理处理程序不会被调用.APUE书上.(未验证)


最后自己总结句:一般还是用return,如果有线程处理程序的时候,再综合考虑.网上有说,尽量不使用线程return等,建议使用 Boost thread library等,封装好的库,避免更多的问题.










引用:

http://hwood.blog.163.com/blog/static/87581175201152354550727/

http://blog.csdn.net/zuifeng503/article/details/8463818

http://stackoverflow.com/questions/8751017/pthread-why-people-bother-using-pthread-exit

http://stackoverflow.com/questions/3692591/return-versus-pthread-exit-in-pthread-start-functions






你可能感兴趣的:(Linux编程,C/C++)