目录
一、线程相关属性的API
1、线程的特殊属性
2、设置线程的属性
3、注意事项
二、线程属性变量的使用步骤
三、相关的API
1、pthread_attr_init/pthread_attr_destroy(初始化、销毁线程属性变量)
2、pthread_attr_setdetachstate、pthread_attr_getdetachstate(获取、设置线程的分离属性)
3、使僵尸进程被系统回收,获取其退出的值的API
(1) pthread_exit(退出线程)
(2)pthread_join、pthread_tryjoin_np(接合指定线程)
四、结合属性代码
五、分离属性的线程结合
- 上述的API都是针对线程属性操作,线程属性是类型为 pthread_attr_t 的变量
- 设置一个线程的属性时,通过以上的函数接口,将需要的属性添加到该类型变量里面,再通过pthread_create( )的第二个参数来创建相应属性的线程
- 设置线程的属性必须要在创建先成功之前
a、定义线程属性变量,并且使用 pthread_attr_init( )初始化。
b、使用 pthread_attr_setXXX( )来设置相关的属性。
c、使用该线程属性变量创建相应的线程。
d、使用 pthread_attr_destroy( )销毁该线程属性变量。
注意
(1)线程缺省的情况下是接合的
(2)线程若是接合的,意味着线程在退出时不会自动释放自身资源,会成为僵尸进程,则 该线程的推出值可以被其他线程获取。
(3)如果不需要某线程的退出值,则将线程设置为分离状态,保证线程不会成为僵尸进程
缺省状态下退出后,会成为僵尸进程,并且保留退出值
其他线程可以通过pthread_exit使其资源被系统回收,还可以获取退出的值
缺省状态下退出后,会成为僵尸进程,并且保留退出值
其他线程可以通过pthread_exit使其资源被系统回收,还可以获取退出的值
注意:
(1)如果线程退出时没有退出值,那么 retval 可以指定为 NULL。(2)pthread_join( )指定的线程如果尚在运行,那么他将会阻塞等待。
(3)pthread_tryjoin_np( )指定的线程如果尚在运行,那么他将会立即出错返回。
#include
#include
#include
#include
#include
#include
void * func (void * arg)
{
while(1)
{
printf("这里是func线程,线程ID :%ld \n" , pthread_self() );
sleep(3);
break ;
}
int * p = calloc(1,4);
*p = 1024444 ;
// 退出本线程并设置返回值的地址(返回了num 的地址)
pthread_exit((void *)p); //返回的内存地址应该时一个堆空间
}
int main(int argc, char const *argv[])
{
// 创建线程
pthread_t t_id = -1 ;
pthread_create( &t_id , //新线程ID号
NULL , // 线程属性, NULL 默认属性
func, // 线程需要执行的例程(新线程需要执行的任务《函数》)
NULL ); // 线程的参数
printf("t_id : %ld\n" , t_id) ;
printf("这里是主函数,线程ID :%ld \n" , pthread_self() );
int * retval ;
// 阻塞等待接合线程
printf("等待 function 线程退出:\n");
pthread_join( t_id , (void*)&retval);
printf("结合线程成功, 退出值为:%d\n" , *retval);
// 尝试接合线程 (非阻塞)
// int ret_val = 0 ;
// if( ret_val = pthread_tryjoin_np( t_id , (void*)&retval))
// {
// fprintf(stderr , "接合失败:%s\n" , strerror(ret_val));
// }
return 0;
}
若线程退出,则退出值为*p的值
#include
#include
#include
#include
#include
#include
void * func (void * arg)
{
while(1)
{
printf("这里是func线程,线程ID :%ld \n" , pthread_self() );
sleep(3);
break ;
}
int * p = calloc(1,4);
*p = 1024444 ;
// 退出本线程并设置返回值的地址(返回了num 的地址)
pthread_exit((void *)p); //返回的内存地址应该时一个堆空间
}
int main(int argc, char const *argv[])
{
// 创建线程属性变量
pthread_attr_t attr ;
// 初始化线程属性
pthread_attr_init(&attr);
// 设置属性信息 (分离属性)
if(pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED))
{
printf("设置分离属性失败!!\n");
}
else{
printf("设置分离属性成功!!\n");
}
// 创建线程
pthread_t t_id = -1 ;
pthread_create( &t_id , //新线程ID号
&attr , // 线程属性(当前设置为分离)
func, // 线程需要执行的例程(新线程需要执行的任务《函数》)
NULL ); // 线程的参数
printf("t_id : %ld\n" , t_id) ;
printf("这里是主函数,线程ID :%ld \n" , pthread_self() );
int * retval ;
int ret_val = 0 ;
// 阻塞等待接合线程
printf("等待 function 线程退出:\n");
if(ret_val = pthread_join( t_id , (void*)&retval))
{
fprintf(stderr , "接合失败:%s\n" , strerror(ret_val));
return -1 ;
}
printf("结合线程成功, 退出值为:%d\n" , *retval);
// 尝试接合线程 (非阻塞)
// int ret_val = 0 ;
// if( ret_val = pthread_tryjoin_np( t_id , (void*)&retval))
// {
// fprintf(stderr , "接合失败:%s\n" , strerror(ret_val));
// }
return 0;
}
输出:结合失败:Invalid atgument
设置为分离属性了,不可以结合