pthread_join()和pthread_detach()二者的区别

0、前言

线程只有两种属性,结合态(joinable)和分离态(detached);

ps:详细示例可以参考该文.

1、pthread_join

1)pthread_join函数的原型

线程默认的属性是结合态。

int pthread_join(pthread_t tid, void ** pthread_return); 

 2)pthread_join函数特点

  • phtread_join函数的第2个参数为void** ,为二重指针,接收的是线程函数中pthread_exit(void* arg);的参数或者是return 的值,可以用来查看pthread_exit传递的参数(如果不关系退出状态,phtread_join的这个参数可以置空,即phtread_join(tid,NULL))。
  • pthread_join函数在线程退出时,用来清理线程资源。
  • phtread_join函数会阻塞调用方,直至pthread_join所指的线程退出。

              -----------------这个特性的优点是,避免出现父线程先于子线程结束的情况,导致子线程还没有结束,主程序退出的情况。

缺点是,阻塞住了主线程,不过我们是多数使用情况下,main()函数在调用pthread_join之后,也不会再调用其他函数,一般只会打印信息之类的了。

因此,默认情况下(在不更改线程属性的情况下)pthread_create需与pthread_join函数同时使用。

3)pthread_join使用示例

void* foo(void*)
{
    while(1)
    {
        sleep(2);
        cout<<"thread"<<endl;
    }
    
}
int func()
{
    cout<<"main func"<<endl;
}
int main()
{
    pthread_t tid;
    pthread_create(&tid,NULL,foo,NULL);
    pthread_join(tid,NULL);//会阻塞主线程
    
    func();//该函数等到子线程执行完才执行
    return 0;
    
}


2、pthread_detach

1)pthread_detach函数原型

int pthread_detach(pthread_t tid);

因为线程默认的状态是结合态的,所以,可以通过pthread_detach函数来设置线程为分离态。

2)pthread_detach函数的特点

  • 使用pthread_detach函数后,使线程处于分离态;
  • 使用pthread_detach函数后,线程在退出后,会自己清理资源
  • 相较pthread_join,使用pthread_detach函数不会阻塞主线程,但是无法获取线程的返回值。
  • pthread_detach使用时,依然需要配合sleep函数或者while(1);,否则无法保证子线程先于主线程执行完。

3)pthread_detach使用示例

pthead_detach的使用可以有两种形式:

在主线程中直接:pthread_detach(tid);

在线程函数中:pthread_detach(pthread_self());

void* foo(void*)
{
    //pthread_detach(pthread_self());//方式2
    int i =10;
    while(i--)
    {
        cout<<"thread"<<endl;
    }
    
}
int func()
{
    cout<<"main func"<<endl;
}
int main()
{
    pthread_t tid;
    pthread_create(&tid,NULL,foo,NULL);
    pthread_detach(tid);//方式1//不会阻塞主线程,
    sleep(2); //避免主线程先退出
    func();//该函数不会等到子线程执行完才执行,会与子线程同时执行
    return 0;
    
}

小结:

1)pthread_join():

创建线程默认的属性就是joinable的,此时需要pthread_create与pthread_join配合使用;

线程创建者通过pthread_join获取线程函数返回值,释放资源等。(jion可以理解为孩子与父母没有分家,有些事还需要父母帮忙完成。)

2)pthread_detach():

使用该函数可以将子线程与主线程分离,子线程结束后,自己回收自己的资源,而不需要主线程回收资源(detach可以理解为孩子与父母分家,事情都需要自己完成)

附录:通过修改线程属性来改变线程的连接、分合状态

除了上述方法外,还可以通过使用设置线程属性来修该线程的状态,以下示例来源于:https://blog.csdn.net/qq_22847457/article/details/89461222


/*DATE:            2019-04-23
 *AUTHOR           CP
 *DESCRIPTION:     设置线程分离属性      
 *如果在创建线程的时候就知道不需要了解线程的终止状态,那么可以修改pthread_attr_t结构体detachstate属性。
 *让线程以分离状态启动。可以使用 pthread_attr_ setdetachstate函数来设置线程的分离状态属性。
 *线程的分离属性有
 *两种合法值
 *    PTHREAD_CREATE_DETACHED分离的
 *    PTHREAD_CREATE_J0INABLE非分离的, 可连接的
 *    int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
 *    int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
 *    便用 pthread_attr_getdetachstate可以获得线程的分离状态属性
 *  
 *    设置线程分离属性的步骤
 *    1.定义线程属性变量 pthread_attr_t attr
 *    2.初始化attr, pthread_attr_init(&attr)  
 *    3.设置线程为分离或非分离 pthread_attr_setdetachstate(&attr,detachstate);
 *    所有的系统都会支持线程的分离状态属性, 
 */
 
#include "apue.h"
#include <pthread.h>
 
void *thread_fun1(void *arg)
{
	printf("I'm new thread 1\n");
	return (void *)1;
}
 
void *thread_fun2(void *arg)
{
	printf("I'm new thread 2\n");
	return (void *)2;
}
 
int main()
{
	pthread_t tid1, tid2;
	int err;
 
	pthread_attr_t attr;   // 定义属性变量
	pthread_attr_init(&attr);  // 初始化属性
	//pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);  // 设置属性状态,置为以分离
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);  // 设置属性状态,置为可连接
 
	
	// 创建线程1
	err = pthread_create(&tid1, &attr, thread_fun1, NULL);
	if (err)
	{
		printf("create new thread 1 failed\n");
		return;
	}
 
	// 创建线程1,默认属性
	err = pthread_create(&tid2, NULL, thread_fun2, NULL);
	if (err)
	{
		printf("create new thread 2 failed\n");
		return;
	}
 
	// 连接线程1
	err = pthread_join(tid1, NULL);
	if (!err)
	{
		printf("join thread 1 success\n");
	}
	else
	{
		printf("join thread 1 failed\n");
	}
 
	// 连接线程2
	err = pthread_join(tid2, NULL);
	if (!err)
	{
		printf("join thread 2 success\n");
	}
	else
	{
		printf("join thread 2 failed\n");
	}
 
	// 销毁属性变量
	pthread_attr_destroy(&attr);
	
	return 0;
}
 

 

  • 9
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值