线程概念
进程中的一条执行流,执行程序中的某段代码
功能:进行多任务处理
以前学习知道,进程就是pcb,是对正在运行程序的描述,通过pcb操作系统可以实现对程序运行的调度管理。线程是进程中的一条执行流,这个执行流在Linux系统下是通过pcb来调度运行的,在Linux系统下实际上没有线程的概念(即无tcb),实际上Linux系统下线程就是一个pcb,这些pcb共用同一个虚拟地址空间,相较于传统pcb更加轻量化,因此也成为轻量级进程。
因此,pcb是线程,是一个轻量级进程,一个进程有多个线程,就相当于由多个轻量级进程组成,一个进程就是一个线程组
注:线程是cpu进行调度的基本单位,进程是操作系统进行资源分配的基本单位
线程之间的共享与独有:
独有:标识符,栈,寄存器,信号屏蔽字,erron,调度优先级
共享:虚拟地址空间,IO信息,信号处理方式,工作目录,用户ID/组ID
多进程/多进程进行任务处理的优缺点:
多线程优点:
1.线程间通信更加灵活方便,除了几种基本的进程间通信方式外还有全局变量,函数传参,因为共用同一个虚拟地址空间,只要知道地址就可以访问同一块空间。
2.线程的创建与销毁成本更低,创建线程只需创建一个pcb,共用的数据只需要通过一个指针指向同一处就行。
3.同一个进程中的线程调度成本更低,因为共用同一个虚拟地址空间,用的时候只需要切换页表就行
多进程的优点:
1.多进程的健壮性,稳定性更高(系统异常以及一些系统调用接口只是对于单个进程)
共同的优点:
1.IO密集型程序,多任务并行处理
2.CPU密集型程序,程序中进行大量数据处理,只要CPU资源足够,就可以同时处理,提高效率
线程控制
线程的创建/退出/取消/等待/分离
创建
#include<pthread.h>
int pthread_creat(pthread* thread, consr pthread_attr_t* attr,void*(*start_routine)(void*),void *arg)
thread:输出型参数,用于获取线程id,线程的操作句柄
attr:线程属性,用于在创建线程的时候设置线程属性,通常置NULL
start routine:函数指针,线程的入口函数-----线程运行的就是这个函数,运行完线程就会退出
arg:通过线程入口函数,传递给线程的参数
返回值:创建成功返回0,失败返回非0--错误编号
tid
线程是一个pcb,每个pcb都有自己pid,pid是一个整型数据
tid:是线程id,线程的操作句柄,准确来说,tid是用户态线程的id,这个id是每个线程独有的地址空间的首地址
线程是一个轻量级pcb,每个pcb都有自己的pid,那么如何确定一个进程的pid呢?在task_struct中有一个tgid—线程组id,等于主线程id,也就是进程id
退出
线程的入口函数运行完毕就会自动退出,通过return 退出,但是main函数的的return是退出整个进程,而不是退出主线程
除此之外
线程退出接口
void pthread_exit(void* retvel)
//retvel 退出返回值
哪个线程调用,哪个退出,主线程退出并不会导致整个进程退出,所有线程退出进程才会退出
int pthread_cancel(pthread_t tid)
//tid 线程tid
终止一个线程,线程是被动取消的
等待
等待一个线程的退出,获取退出线程的返回值,回收线程所占资源
线程由一个属性,默认创建出来的这个属性是joinable,出于这个属性的线程推出后,需要被其他线程等待获取返回值回收资源
int pthread_join(pthread_t tid,void** retvel)
//tid:等待线程的tid
//retvel:输出型参数,用于返回线程的返回值
等待指定线程退出,获取其返回值,是一个阻塞函数,没有退出则一致等待
默认情况下,线程必须被等待,否则会造成资源泄露
分离
线程分离:将一个线程的属性joinable变成detach属性
一个线程属性如果是joinable,则必须被等待
一个线程属性如果是detach,线程在退出时会自动释放资源,不需要被等待
int pthread_detach(pthread_t tid);
分离线程的情况:对线程退出的返回值不感兴趣,不想获取返回值,并且不想等待线程退出
pthreat_t pthread_self(void);
//获取当前线程的tid