开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 17 天,点击查看活动详情
引入多线程的动机
进程有什么问题呢?
- 进程切换开销大
- 进程通信代价大
- 进程间的并发粒度较粗,并发度不高
进程的两个重要功能
独立分配,被调度分派执行
进程作为系统资源分配和保护的独立单位,不需要频繁的切换
线程作为系统调度和分配的基本单位,能轻装运行,会被频繁的调度和切换
与进程相比,线程的优点
- 快速线程切换。同以进的多线程切换只需改变堆栈和寄存器,地址空间不变。
- 通信易于实现
- 减少管理开销
- 并发程度提高
多线程环境中的进程和线程
线程是操作系统进程中能够独立执行的实体,是处理器调度和分配的基本单位。线程是进程的组成部分,这些进程共享线程多获得的内存空间和资源。
线程组成
- 线程唯一标识及其线程状态信息
- 未运行时保存的线程上下文;可把线程看成进程中一个独立的程序计数器(PC)在操作
- 核心栈,核心态下工作时,保存参数,函数调用时的返回值等
- 用于存放线程局部变量器用户栈的私有存储区
线程又称轻量级进程
- 线程运行在进程的上下文中,并使用进程的资源和环境
- 系统调度的基本单位是线程而不是进程,每当创建一个进程时,至少要同时为该进程创建一个线程,否则该进程无法被调度执行。
线程的状态
线程状态有:运行、就绪和阻塞态等,线程的状态转换与进程的转换类似。
挂起状态对线程(在描述上)是没有意义的,如果进程挂起后被对换出内存,则它的所有线程因共享了进程的地址空间,也必须对换出去。
线程的实现
从实现的角度看,线程分为:用户级线程、内核级线程、混合式线程
内核级线程
线程管理的所有工作都是由内核完成的,应用程序只有一个访问内核级线程设施的API。内核维护进程和线程的上下文信息,调度对象是线程。
优点
内核可以调度同一个进程中的所有线程,内核自身也可以是多线程的(多cpu)
缺点
线程需要切换到内核,开销比较大。
用户级线程
用户级线程是指线程的管理由应用程序完成,在用户空间中实现,内核无需感知线程的存在。
优点
线程切换的开销小、所有线程管理的数据结构均在用户空间中、可以节省模式转换开销和内核的宝贵资源、可以不修改内核,用户级线程就可以运行在任何操作系统中
缺点
用户级线程阻塞就会导致整个系统的阻塞、不能利用多处理计数
进程的控制和管理
把处于同一状态的所有PCB链接在一起的数据结构称为进程队列。
进程切换是让处于运行态的进程中断运行,让出处理器,也就是做一次进程上下文切换,即保存老进程状态而装入被保护/保存了的新进程的状态,以便新进程运行。
当中断发生的时候,暂时中断正在执行的用户进程,把处理器的状态从用户状态切换到内核状态。
对于进程的控制和管理包括创建进程、阻塞进程、唤醒进程、挂起进程、激活进程、终止进程和撤销进程。
进程创建
- 申请空白的pcb
- 申请内存资源
- 初始化进程控制块
- 将新进程插入就绪队列
进程撤销
- 从pcb集合中检索出该进程的pcb
- 将被终止进程的所有资源归还父进程或者系统
进程阻塞
- 进程调用阻塞原语把自己阻塞,立即停止执行,保存现场信息
- 改变进程的状态————运行态改为等待态,插入有关等待队列
进程唤醒
- 把阻塞进程从等待该事件的阻塞队列中移除,其状态改成就绪态
- 等待被调度
进程挂起
- 检测要被挂起的状态,然后把相应的状态变成挂起状态
- 把进程的pcb非常驻部分交换到磁盘的对换区
进程激活
- 把进程pcb非常驻部分从磁盘中调入到内存中
- 然后把状态修改过来