线程概念*
线程是进程中的一条执行流,是CPU调度运行的基本单位,在Linux下通过pcb实现(一个执行流对应内核态就是一个pcb),一个进程中可以有多个pcb,并且这些pcb共享进程中的大部分资源(相较于传统pcb更为轻量化),而我们不能直接操作内核中的pcb而是通过用户态的线程来操作(通过tid来完成用户态线程与内核态pcb的一一对应),因此线程被称为轻量级进程;
线程不分父与子,只有主线程和辅线程;
线程间通信方式:
所有可用于进程间通信的方式都可以用于线程间通信,除此之外还有全局变量和函数传参(线程之间用的是同一块虚拟地址空间);
线程之间的独有与共享:
独有:标识符,寄存器(上下文数据),程序计数器,栈,信号阻塞集合(信号屏蔽字),errno…
共享:虚拟地址空间(共享内存资源),IO信息(共享文件资源),信号处理方式,工作路径…
线程控制
Linux下操作系统未提供实现线程的系统调用接口所以只有在用户态封装的库函数用于线程控制
创建
每个线程创建出来之后会在栈上开辟一段空间用于存储各项描述信息,创建线程时返回了tid,tid就是该块空间的地址;
pthread_t tid;
//线程pid;
int pthread_create(pthread_t *tid, pthread_attr_t *attr, void *(*thread_routine)(void*), void *arg);
//pthread_t *tid:传入一个pthread_t类型变量地址获取线程id;
//pthread_attr_t *attr:线程属性通常为NULL;
//void *(*thread_routine)(void*):函数地址,线程入口函数;
//void *arg:向线程入口函数传递的参数;
//成功返回0,失败返回非0;
终止
①在线程入口函数中return,线程入口函数运行完毕则终止该线程;
②调用void pthread_exit(void *retval);//retval:线程退出返回值
入口函数在任意位置调用都可以退出线程;
③void pthread_cancel(pthread_t *tid);//tid:被推出的线程id
想让谁退出就输入谁的id;
等待*
线程退出后在栈上开辟的空间的等资源不会自动释放,需要其他线程等待处理来获取返回值,释放所有资源
int pthread_join(pthread_t *tid, void **retval);
//是一个阻塞接口,没等到就一直等着;
//tid:要等待的线程id;
//void **retval:用于获取线程退出返回值;
//成功返回0,失败返回非0;
分离*
每个线程都具有分离属性,该属性默认为joinable状态,处于该状态的线程不会自动释放资源需要被等待;
该属性还有一个detach状态,处于该状态的线程不需要也不允许被等待,结束后直接自动释放资源;
int pthread_detach(pthread_t tid);
//要设置为detach状态的线程id;
多线程与多进程用于多任务并发处理时的优缺点:
多线程优点:
①线程之间的通信更加灵活方便;
②线程创建和销毁成本更低;
③线程间的切换调度成本更低;
多进程优点:
进程占用了更多的资源,更加稳定、健壮;
(并发处理虽然会提高程序运行效率,但是如果执行流过多会提高运行调度的成本)