线程的分离状态决定一个线程以什么样的方式来终止自己。
线程的默认属性,一般是非分离状态,
这种情况下,原有的线程等待创建的线程结束。
只有当pthread_join()函数返回时,创建的线程才算终止,才能释放自己占用的系统资源。
而分离线程没有被其他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源。
程序员应该根据自己的需要,选择适当的分离状态。
关于分离线程的一种用法(转)
讲到分离线程,先得从僵尸进程讲起(抱歉,确实不知道线程是否有僵尸一说)。
关于僵尸进程:一般情况下进程终止的时候,和它相关的系统资源也并不是主动释放的,而是进入一种通常称为“僵尸”(zombie)的状态。它所占有 的资源一直被系统保留,直到它的父进程(如果它直接的父进程先于它去世,那么它将被init进程所收养,这个时候init就是它的父进程)显式地调用 wait系列函数为其“收尸”。为了让父进程尽快知道它去世的消息,它会在它死去的时候通过向父进程发送SIGCHLD信号的方式向其“报丧”。
所以一旦父进程长期运行,而又没有显示wait或者waitpid,同时也没处理SIGCHLD信号,这个时候init进程,就没办法来替子进程来收尸。这个时候,子进程就真的成了”僵尸“了。
同理:
如果一个线程调用了这个函数,那么当这个线程终止的时候,和它相关的系统资源将被自动释放,系统不用也不能用pthread_join()等待其退 出。有的时候分离线程更好些,因为它潜在地减少了一个线程回收的同步点,并且pthread_join()这个API确实也是相当地难用。
为了让主线程省去去子线程收尸的过程,可以使用
int pthread_detach(pthread_t thread);
来让子线程处于分离状态,就不需要父线程再pthread_join了。
我们来看一种分离线程的用法。上次别人问道一种情况,我发现必须要分离子线程:
void* task1(void*);
void usr();
int p1;
int main()
{
p1=0;
usr(); //调用这个认为是你的触发函数
getchar();
return 1;
}
void usr()
{
pthread_t pid1;
pthread_attr_t attr;
/*这里做你的事情*/
if(p1==0)
{ pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); //因为你的线程不便于等待的关系,设置为分离线程吧
pthread_create(&pid1, &attr, task1, NULL);
}
}
void* task1(void *arg1)
{
p1=1; //让子线程不会被多次调用
int i=0;
printf("thread1 begin./n");
for(i=0;i<100;i++)
{
sleep(2);
printf("At thread1: i is %d/n",i);
usr(); //继续调用
}
pthread_exit();
}
我 们看到,在这里task1这个线程函数居然会多次调用其父线程里的函数,显然usr函数里,我们无法等待task1结束,反而task1会多次调用 usr,一旦我们在usr里pthread_join,则在子线程退出前,有多个usr函数会等待,很浪费资源。所以,此处,将task1设置为分离线程 是一种很好的做法。