虚拟地址:
线程:
概念:线程是轻量级进程,一般是一个进程中的多个任务。
进程是系统中最小的资源分配单位。(竞争计算机资源的最小单位)(进程能分配硬件资源,线程不行)线程是系统中最小的执行单位。
特征:
1、共享资源(除了栈区都共享)-->每个进程有独立的栈区,其他空间其实都用的是所从属的进程的,有效减少内存开销
2、效率高 30%
3、三方库: pthread clone posix
3.1 编写代码头文件: pthread.h
3.2 编译代码加载库: -lpthread library
libpthread.so
gcc 1.c -lpthread
缺点:
1,线程和进程相比,稳定性,稍微差些(一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程稳定。)
2,线程的调试gdb,相对麻烦些。
线程与进程区别:
变量开销:进程:3G(物理内存总量),线程:8M(单个程序栈的最大空间)
资源:
线程比进程多了共享资源。 IPC(进程间通信)
线程又具有部分私有资源。
进程间只有私有资源没有共享资源。
空间:
进程空间独立,不能直接通信。
线程可以共享空间,可以直接通信。
线程的设计框架
创建多线程 --> 线程空间操作 --> 线程资源回收
线程创建:pthread_create():
int pthread_create(
pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
功能:该函数可以创建指定的一个线程。
参数:thread 线程id,需要实现定义并由该函数返回。
attr 线程属性,一般是NULL,表示默认属性。
start_routine 指向指针函数的函数指针。
本质上是一个函数的名称即可。称为
回调函数,是线程的执行空间。
arg 回调函数的参数,即参数3的指针函数参数。
如果想要传多个参数:使用结构体
返回值:成功 0
失败 错误码
注:
一次pthread_create执行只能创建一个线程。
每个进程至少有一个线程称为主线程。
主线程退出则所有创建的子线程都退出。
主线程必须有子线程同时运行才算多线程程序。
线程id是线程的唯一标识,是CPU维护的一组数字。
pstree 查看系统中多线程的对应关系。
多个子线程可以执行同一回调函数。
pthread_self():
pthread_t pthread_self(void);
功能:获取当前线程的线程id
参数:无
返回值:成功 返回当前线程的线程id
失败 -1;
线程退出:
自行退出-->自杀-->exit()
void pthread_exit(void *retval); //与return的效果类似
功能:子线程自行退出
参数: retval 线程退出时候的返回状态,临死遗言。
返回值:无
强制退出-->他杀-->pthread_cancel()
int pthread_cancel(pthread_t thread);
功能:请求结束一个线程
参数:thread 请求结束一个线程tid
返回值:成功 0
失败 -1;
pthread_join()
int pthread_join(pthread_t thread, void **retval);
功能:阻塞回收。通过该函数可以将指定的线程资源回收,该函数具有
阻塞等待功能,如果指定的线程没有结束,则回收线程会阻塞。
参数:thread 要回收的子线程tid
retval 要回收的子线程返回值/状态。-->ptread_exit(值);
返回值:成功 0
失败 -1;
为什么要用ret要使用二级void指针:
因为ret期望来存储类似于函数指针,字符串(字符串使用字符数组存储)的值,这种变量本身就是一级指针,如果我们要在传参这种操作中能使被调修改主调,必须使用*运算,所以我们传进去的二级指针
期望的传参操作:
void* ret;
pthread_create(&tid,NULL,th,NULL);
pthread_join(tid,&ret); //传入一级指针地址
printf("ret %s\n",(char *)ret); //转换为需要的类型
printf("ret %d\n",*((char *)ret)); //取两次*运算
子线程的回收策略:
1、如果预估子线程可以有限范围内结束则正常用pthread_join等待回收。
2、如果预估子线程可能休眠或者阻塞则等待一定时间后强制回收。
3、如果子线程已知必须长时间运行则,不再回收其资源。
期望传回的地址:
原理:子线程退出的时候,可以返回一个内存地址
该值所在的内存中可以存储任何数据,只要
地址存在,则数据都可以正常返回。
地址有三种:
0、栈区变量 错误,子线程结束该地址失效。
1、全局变量 失去意义,本质可以直接访问。
所以可以传回的地址:
2、静态变量
3、堆区变量
分离属性(attribute):
设置分离属性,目的线程消亡,自动回收空间。
pthread_attr_init
int pthread_attr_init(pthread_attr_t *attr);
功能,初始化一个attr的变量
参数:attr,需要变量来接受初始值
返回:0 成功,
非0 错误
pthread_attr_destroy
int pthread_attr_destroy(pthread_attr_t *attr);
功能:销毁attr变量。
attr,属性变量
返回:0 成功,
非0 错误;
pthread_attr_setdetachstate
功能:把一个线程设置成相应的属性
参数,attr,属性变量,有init函数初始化他。
detachstate:有2个可选值,
设置分离属性:
PTHREAD_CREATE_DETACHED(分离线程)
PTHREAD _CREATE_JOINABLE(非分离线程)
第二种设置分离属性的函数:pthread_deatch
int pthread_deatch(pthread_t thread);
功能,设置分离属性
参数,线程id号,填自己的id
清理函数:
pthread_cleanup_push()
void pthread_cleanup_push(void (*routine)(void *), void *arg);
功能:注册一个线程清理函数
参数,routine,线程清理函数的入口
arg,清理函数的参数。
返回值,无
需要满足以下条件才会调用注册的回调函数:
1.线程被取消的时候(pthread_cancel)
2.线程主动退出的时候(pthread_exit)
3.pthread_cleanup_pop的参数为非0值(pthread_cleanup_pop)
pthread_cleanup_pop:
void pthread_cleanup_pop(int execute);
功能:调用清理函数
execute,非0 执行清理函数
0 ,不执行清理
返回值,无