Linux高阶——1109—线程函数线程属性线程分类
目录
1、pthread_cancel函数
代码
成功截图
2、pthread_testcancel函数
代码
成功截图
3、pthread_equal函数
4、pthread_exit函数
5、线程属性
使用修改线程属性
代码
成功截图
6、线程分类
1、用户级线程
2、混合型线程
7、怎样区分线程和进程
8、什么是线程,通过一句话概述
1、pthread_cancel函数
pthread_cancel(pthread_t tid)——传入目标线程tid,杀死取消线程
如果目标线程没有系统调用事件,那么此线程无法被取消
如果目标线程回收到-1,表示该线程是被cancel杀死的
线程返回值不允许为-1,保留给cancel
代码
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<signal.h>
#include<pthread.h>
void * jobs(void* arg)
{
while(1)
sleep(1);
//pthread_testcancel();
}
int main ()
{
pthread_t tid;
pthread_create(&tid,NULL,jobs,NULL);
sleep(3);
pthread_cancel(tid);
void * reval;
pthread_join(tid,&reval);
printf("join success,reval %d\n",(int)reval);
return 0;
}
成功截图
2、pthread_testcancel函数
使用sleep函数是触发系统调用后,进行睡眠,使用printf函数是触发系统调用后,输出
pthread_testcancel()——只触发系统调用,而没有任务
代码
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<signal.h>
#include<pthread.h>
void * jobs(void* arg)
{
while(1)
pthread_testcancel();
}
int main ()
{
pthread_t tid;
pthread_create(&tid,NULL,jobs,NULL);
sleep(3);
pthread_cancel(tid);
void * reval;
pthread_join(tid,&reval);
printf("join success,reval %d\n",(int)reval);
return 0;
}
成功截图
3、pthread_equal函数
pthread_equal——比较两个线程id是否相等,不相等返回0,相等返回nonzero
4、pthread_exit函数
退出方式:
1、return
普通线程执行return,线程退出返回
主控线程执行return,进程退出,释放所有线程
2、exit
任意线程执行exit,杀死进程,释放所有线程
3、cancel
取消单个线程
4、pthread_exit
调用pthread_exit函数,只退出当前线程,可以利用它结束主线程
主线程可以创建普通线程,普通线程也可以创建普通线程,普通线程也可以回收普通线程
线程函数,所有线程都可以使用,例如线程创建,线程回收,线程取消等等
使用方法:
5、线程属性
在线程创建之前,通过属性,预制线程
线程属性类型:pthread_attr_t,包含:
1、线程的警戒缓冲区大小:4096(4K)
2、线程的优先级指针:一般软件研发,没有特别要求功能需求,不修改进程线程优先级
3、线程的退出状态:可以线程创建之前,决定线程变为分离态
4、线程栈地址
5、线程栈大小
4-5:修改线程栈大小,提升线程的创建数量
使用修改线程属性
1、定义属性结构体
2、设置结构体成员
pthread_attr_init(&attr)——初始化申请空间
pthread_attr_destroy(&attr)——释放属性结构体
pthread_attr_getdetachstate(&attr,&detachstate)——获取属性中的退出状态传出,第一个参数是结构体地址,第二个是传出参数,是参数
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED)——获取属性中的栈地址与大小
pthread_attr_getstack(&attr,void** stackaddr,int* stacksize)——获取属性中的栈地址与大小
pthread_attr_setstack(&attr,void* stackaddr,int stacksize)——设置属性的栈大小与地址
3、使用自定义属性创建线程
pthread_create(&tid,&attr,jobs,NULL)
代码
#include<stdio.h>
#include<pthread.h>
void * jobs(void* arg)
{
while(1);
}
int main(int argc, const char* argv[])
{
pthread_attr_t attr;
pthread_attr_init(&attr);
int detachstate;
pthread_attr_getdetachstate(&attr,&detachstate);
if(detachstate==PTHREAD_CREATE_JOINABLE)
printf("JOIN\n");
else
printf("JDETACH\n");
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
pthread_t tid;
pthread_create(&tid,&attr,jobs,NULL);
int err;
if((err=pthread_join(tid,NULL))>0)
{
printf("join fail %s\n",strerror(err));
exit(0);
}
}
成功截图
6、线程分类
线程分为内核级线程、用户级线程和混合型线程
1、用户级线程
用户级线程不是系统自带的,很多操作系统可能不支持线程技术,下载安装第三方线程库,这类一般为用户级线程
用户级线程无法被系统分发时间片,主线程放弃时间片,根据就近原则,用户级可以使用时间片
用户级线程不能并行执行,只能并发执行,相比于内核线程,得到的时间片更少,执行效率更低
用户级线程安装在用户层,调度切换无需系统干预,切换开销更小
无论内核级还是用户级,并发特性都存在,cpu使用效率更高
用户级线程并行特性(两个核挂到两个线程上,都获得时间片)没有了,但是并发特性(两个线程可以共用一个时间片)还存在
区别
定义:
- 并发:多个任务在时间上重叠,但任一时刻只有一个任务在处理机上运行。
- 并行:多个任务在同一时刻在不同的处理机上同时运行。
侧重:
- 并发:侧重于在同一实体上的时间重叠。
- 并行:侧重于在不同实体上的同时执行。
处理方式:
- 并发:在一台处理器上“同时”处理多个任务,通过时间片切换实现。
- 并行:在多台处理器上同时处理多个任务,每个处理器独立执行一个任务。
2、混合型线程
可以创建内核对象,可以被系统直接分配cpu资源
线程库安装在用户层,切换开销更小
7、怎样区分线程和进程
只要分配内存是进程,不分配内存是线程
8、什么是线程,通过一句话概述
答:线程就是寄存器和栈
寄存器:cpu的元件——调度单位才能使用寄存器,访问cpu
栈:线程得到寄存器时,有可能被中断,寄存器中的值需要被保存起来,得到时间片以后,需要恢复值,保存和恢复现场