多线程
当引入线程后,进程可以看作是 资源的集合,线程可以看作是 执行单元,线程之间共享进程的某些资源,比如文件描述符等等,这方便了线程之间的通信,每个线程都有自己的堆栈(因为线程的启动函数可能不同,甚至可能递归)
简单来说就是,同一个进程内的线程可以共享一些资源,每个线程都有自己的执行环境
初始线程(主线程)
主线程是特殊的(主线程就是第一个线程,就是main函数),大多数情况下,初始线程是运行在进程堆栈上的,普通线程的堆栈空间是受限的,从主线程中返回会导致进程结束(所有线程终止),其他线程不会
并发系统的基本功能
-
执行环境,并发实体(进程/线程) 的状态,并发系统需要有维护他们状态的方式
-
调度,切换执行环境
-
同步,协调访问共享资源
线程的两个操作
-
连接:
在线程A中连接线程B,这句话的意思是,线程A会等待线程B结束后在执行(阻塞情况),线程结束时,可能会有返回值等信息,操作系统会假设这些是用户需要的,所以线程不会被回收,换句话说,线程即使做完了工作仍旧持有它所占有的资源(保留其虚拟内存),包括 堆栈 等等系统资源,这也叫做 僵尸线程
一旦线程被连接,也就是说有其他线程接收返回值,那么这个线程就可以被回收了
-
分离:
分离的意思就是直接告诉操作系统,该线程无需被连接,换句话说就是返回值不需要传递给其他线程,这时候,操作系统会在线程结束工作后自动将其资源回收
线程能够自己分离自己或者让其他线程分离自己,但是不能自己连接自己,这会造成死锁,导致线程永远无法结束,只能让其他线程连接自己
线程的四个基本状态


线程在创建完毕后处于 就绪态,当 被调度 后转到 运行态,等待某些事件时转为 阻塞态,工作完成后或者被取消转到 终止态
阻塞态 可能是因为以下事件:
- 试图加锁一个已经被锁住的互斥量
- 等待某个条件变量
- 执行无法立即完成的IO操作
- 内存页错误
线程通常从启动函数中返回来终止自己,如果终止线程没有被分离或者连接,那么它将一直处于终止状态
需要注意的是,线程的返回值不要和它自己的堆栈相关,因为当线程返回时,其资源被释放,在去访问已经被释放的地址很可能会发生错误
线程的生命周期
线程创建 -> 线程启动 -> 运行和阻塞 -> 终止 -> 回收
线程安全和可重入
表示代码被多个线程调用不会有危害
可以通过以下方式实现线程安全:
(粒度渐细)
-
函数调用串行化: 在进入函数前加锁
-
保护临界代码:对访问共享数据的代码进行保护
-
保护临界数据:对访问共享数据进行保护
-
线程私有存储:每个线程可以独立存储各自的数据
可重入 就是用来形容 有效的线程安全,他应该避免对 静态数据 的依赖(全局变量、静态变量)
线程适用场景
-
计算密集型:消耗CPU资源
-
IO密集型:消耗IO资源(计算机与外部设备进行数据交换)
posted on
浙公网安备 33010602011771号