目录
一、线程的属性----分离属性(attr->attribute)
2.如何创建分离属性的线程? -> pthread_attr_setdetachstate() -> man 3
方法一:添加一个分离属性到一个属性变量中,然后使用属性变量去创建一个线程,那么创建出来的线程就是具有分离属性的线程。
练习1: 验证一个分离属性的线程退出,主线程还可不可以去接合(阻塞等待回收)它? --不可以
练习3: 使用pthread_detach之后来验证pthread_join阻塞失败?(注意分离属性时间生效的问题)
练习4:验证设置了分离属性的线程,在进程中最多能创建多少条??? --没有限制
1.一般主线程不用于去处理任务,只是控制子线程状态,例如取消,接合.. -> pthread_cancel() -> man 3 pthread_cancel
2.设置线程响应取消的状态。 -> pthread_setcancelstate() -> man 3 pthread_setcancelstate
3.设置线程响应取消的类型。 -> pthread_setcanceltype() -> man 3 pthread_setcanceltype
1)压栈线程的取消例程函数-> pthread_cleanup_push()
2)弹栈线程的取消例程函数 --> pthread_cleanup_pop()
练习5: 子线程收到主线程给自己发送的取消请求,不要马上取消,而是先打印一句话"I recv cancel!\n",再响应取消。顺便使用这个练习,验证以上这3种情况。
4)关闭有名信号量。 -> sem_close() -> man 3 sem_close
5)删除有名信号量。 -> sem_unlink() -> man 3 sem_unlink
2)初始化无名信号量。 -> sem_init() -> man 3 sem_init
5)销毁无名信号量。 -> sem_destroy() -> man 3 sem_destroy
一、线程的属性----分离属性(attr->attribute)
1.什么是分离属性?
首先分离属性是线程的一个属性,有了分离属性的线程,不需要别的线程去接合自己的(回收自己的资源)。但是虽然说是分离的,但是进程退出了,该线程还是会退出的。
设置了分离属性的线程 -> 不需要pthread_join()
设置了非分离属性的线程 -> 需要pthread_join() -> 默认创建的普通属性线程就是非分离线程。
2.如何创建分离属性的线程? -> pthread_attr_setdetachstate() -> man 3
pthread_attr_setdetachstate
方法一:添加一个分离属性到一个属性变量中,然后使用属性变量去创建一个线程,那么创建出来的线程就是具有分离属性的线程。
1)定义一个属性变量 -> 数据类型:pthread_attr_t
pthread_attr_t attr;
2)初始化属性变量。 -> pthread_attr_init() -> man 3 pthread_attr_init
#include <pthread.h>
int pthread_attr_init(pthread_attr_t *attr);
参数:
attr:未初始化的属性变量
返回值:
成功:0
失败:非0错误码
3)设置分离属性到属性变量中。
#include <pthread.h>
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
参数:
attr:已经初始化过的属性变量
detachstate:
PTHREAD_CREATE_DETACHED -> 分离属性
PTHREAD_CREATE_JOINABLE -> 非分离属性(默认状态)
返回值:
成功:0
失败:非0错误码
4)使用属性变量去创建一个新的线程。
pthread_create(&tid,&attr,.....); -> 创建出来的线程就是分离属性的线程,不需要pthread_join()
5)销毁属性变量。 -> pthread_attr_destroy() -> man 3 pthread_attr_destroy
int pthread_attr_destroy(pthread_attr_t *attr);
参数:
attr:已经初始化过的属性变量
返回值:
成功:0
失败:非0错误码
#include<stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <stdlib.h>
//方法1 : 如何创建具有分离属性的线程
void* start_routine(void *arg)
{
printf("[%lu]start_routine\n",pthread_self()); //pthread_self打印当前线程的ID号
sleep(3);
}
int main()
{
//1、定义一个线程属性变量
pthread_attr_t attr;
//2、初始化清空属性变量
pthread_attr_init(&attr);
//3、把分离属性加入到属性变量中
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
//4、创建一条具有分离属性的子线程
pthread_t thread;
pthread_create(&thread,&attr,start_routine,NULL);
//5、销毁属性变量
pthread_attr_destroy(&attr);
pause();//暂停自己
}
练习1: 验证一个分离属性的线程退出,主线程还可不可以去接合(阻塞等待回收)它? --不可以
#include<stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <stdlib.h>
//方法1 : 如何创建具有分离属性的线程
void* start_routine(void *arg)
{
int cnt = 10;
while(cnt--)
{
printf("[%s] is job.... [%d]\n",__FUNCTION__,cnt); //pthread_self打印当前线程的ID号
sleep(1);
}
}
int main()
{
//1、定义一个线程属性变量
pthread_attr_t attr; //不要写成pthread_attr_t *attr;
//2、初始化清空属性变量
pthread_attr_init(&attr);
//3、把分离属性加入到属性变量中
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
//pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);//线程的默认状态非分离属性
//4、创建一条具有分离属性的子线程
int ret;
pthread_t tid;
ret = pthread_create(&tid,&attr,start_routine,NULL);
if(ret != 0)
{
perror("pthread_create fail");
return -1;
}
int cnt = 0;
while(cnt--)
{
printf("[%s] is job....\n",__FUNCTION__); //pthread_self打印当前线程的ID号
sleep(1);
}
ret = pthread_join(tid,NULL);
if(ret != 0)
{
perror("pthread_join fail");
return -1;
}
//5、销毁属性变量
pthread_attr_destroy(&attr);
printf("main is over\n");
return 0;
}
/*
int *x,*y;
get xy(int *x,int *y)
{
*x = 10;
*y = 20;
}
get_xy(x,y);//x,y值没有改变
int x,y;
get_xy(int *x,int *y);
{
*x = 10;
*y = 20;
}
get_xy(&x,&y);//x,y值有改变
*/
练习2: 验证一个分离属性的线程,在进程退出时,该分离属性的线程还会不会继续运行? --不会运行了
#include<stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <stdlib.h>
//方法1 : 如何创建具有分离属性的线程
void* start_routine(void *arg)
{
int cnt = 10;
while(cnt--)
{
printf("[%s] is job.... [%d]\n",__FUNCTION__,cnt); //pthread_self打印当前线程的ID号
sleep(1);
}
}
int main()
{
//1、定义一个线程属性变量
pthread_attr_t attr; //不要写成pthread_attr_t *attr;
//2、初始化清空属性变量
pthread_attr_init(&attr);
//3、把分离属性加入到属性变量中
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
//pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);//线程的默认状态非分离属性
//4、创建一条具有分离属性的子线程
int ret;
pthread_t tid;
ret = pthread_create(&tid,&attr,start_routine,NULL);
if(ret != 0)
{
perror("pthread_create fail");
return -1;
}
int cnt = 5;
while(cnt--)
{
printf("[%s] is job....[%d]\n",__FUNCTION__,cnt); //pthread_self打印当前线程的ID号
sleep(1);
}
//添加了分离属性的子线程,主线程不需要调用pthread_join去结合它
//5、销毁属性变量
pthread_attr_destroy(&attr);
printf("main is over\n");
return 0;
}
/*
int *x,*y;
get xy(int *x,int *y)
{
*x = 10;
*y = 20;
}
get_xy(x,y);//x,y值没有改变
int x,y;
get_xy(int *x,int *y);
{
*x = 10;
*y = 20;
}
get_xy(&x,&y);//x,y值有改变
*/
#include<stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
//方法1 : 如何创建具有分离属性的线程
/*
练习1: 验证一个分离属性的线程退出,主线程还可不可以去接合(阻塞等待回收)它?
练习2: 验证一个分离属性的线程,在进程退出时,该分离属性的线程还会不会继续运行?
*/
void* start_routine(void *arg)
{
printf("[%lu]start_routine\n",pthread_self()); //pthread_self打印当前线程的ID号
sleep(3);
}
int main()
{
//1、定义一个 线程属性变量
pthread_attr_t attr;
//2、初始化清空 属性变量
pthread_attr_init(&attr);
//3、把分离属性 加入 到 属性变量中
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
//4、创建一条具有分离属性的子线程
pthread_t thread;
pthread_create(&thread,&attr,start_routine,NULL);
//5、销毁属性变量
pthread_attr_destroy(&attr);
//阻塞等待子线程退出,回收资源
int ret = pthread_join(thread,NULL);
if(ret != 0){
printf("pthread_join error\n");
}
}
现象:
pthread_join失败,回收资源失败
方法二:先创建一个普通线程,然后在线程中调用一个设置分离属性的函数,那么这个线程就变成分离的属性。
1)设置线程本身的属性为分离属性。 -> pthread_detach() -> man 3 pthread_detach
#include <pthread.h>
int pthread_detach(pthread_t thread);
函数作用:
设置分离属性给线程
参数:
thread:需要设置分离属性的线程的ID号
返回值:
成功:0
失败:非0错误码
2)获取线程的ID号。 -> pthread_self() -> man 3 pthread_self
#include <pthread.h>
pthread_t pthread_self(void);
参数:
无
返回值:线程的ID号。
#include<stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <stdlib.h>
//方法1 : 如何创建具有分离属性的线程
void* start_routine(void *arg)
{
//在子线程的内部 设置 分离属性
pthread_detach(pthread_self());
printf("[%lu]start_routine\n",pthread_self()); //pthread_self打印当前线程的ID号
}
int main()
{
//4、创建一条具有分离属性的子线程
pthread_t thread;
pthread_create(&thread,NULL,start_routine,NULL);
//pause();
}
现象:
练习3:
使用pthread_detach之后来验证pthread_join阻塞失败?(注意分离属性时间生效的问题)
#include<stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <stdlib.h>
//方法1 : 如何创建具有分离属性的线程
void* start_routine(void *arg)
{
pthread_detach(pthread_self()); //写法二
int cnt = 10;
while(cnt--) //子线程想要工作10秒
{
printf("[%s] is job.... [%d]\n",__FUNCTION__,cnt); //pthread_self打印当前线程的ID号
sleep(1);
}
//pthread_exit(NULL);
}
int main()
{
int ret;
pthread_t tid;
ret = pthread_create(&tid,NULL,start_routine,NULL);
if(ret != 0)
{
perror("pthread_create fail");
return -1;
}
//pthread_detach(tid); //写法一
int cnt = 5;
while(cnt--) //主线程工作5秒之后是退出还是等待---退出
{
printf("[%s] is job....[%d]\n",__FUNCTION__,cnt); //pthread_self打印当前线程的ID号
sleep(1);
}
//添加了分离属性之后,pthread_join就不用了
/* ret = pthread_join(tid,NULL);
if(ret != 0)
{
perror("pthread_join fail");
return -1;
} */
printf("main is over\n");
return 0;
}
练习4:验证设置了分离属性的线程,在进程中最多能创建多少条??? --没有限制
#include<stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <stdlib.h>
//方法1:如何创建具有分离属性的线程
void* start_routine(void *arg)
{
//在子线程的内部设置分离属性
pthread_detach(pthread_self());
printf("[%lu]start_routine\n",pthread_self()); //pthread_self打印当前线程的ID号
}
int main()
{
//4、创建一条具有分离属性的子线程
pthread_t thread;
int cnt=0;
while(1)
{
int ret= pthread_create(&thread,NULL,start_routine,NULL);
if(ret != 0){
printf("pthread_create error\n");
break;
}
printf("cnt:%d\n",cnt++);
}
}
总结:
无论是否添加了分离属性的线程,理论上创建的线程的数量没有限制。