第四章.线程
1.进程与线程
- 进程是操作系统进行资源分配的基本单位
- 线程是调度的基本单位
进程中的所有线程共享该进程的状态和资源,进程和线程的关系如下图:
从性能上比较,线程具有如下优点:
- 在一个已有进程中创建一个新线程比创建一个全新进程所需的时间要少许多
- 终止一个线程比终止一个进程花费的时间少
- 同一进程内线程间切换比进程间切换花费的时间少
- 线程提高了不同的执行程序间通信的效率(在大多数操作系统中,独立进程间的通信需要内核的介入,以提供保护和通信所需要的机制。但是,由于在同一个进程中的线程共享内存和文件,它们无须调用内核就可以互相通信)
2.线程状态
和进程一样,线程的关键状态有运行态、就绪态和阻塞态。一般来说,挂起态对线程没有什么意义。这是由于此类状态是一个进程级的概念。特别地,如果一个进程被换出,由于它的所有线程都共享该进程的地址空间,因此它们必须都被换出
有4种与线程相关的基本操作:
- 派生:在典型情况下,当派生一个新进程时,同时也为该进程派生了一个线程。随后,进程中的线程可以在同一进程中派生另一个线程,并为新线程提供指令指针和参数;新线程拥有自己的寄存器上下文和栈空间,且被放置在就绪队列中
- 阻塞:当线程需要等待一个事件时,它将被阻塞(保存它的用户寄存器、程序计数器和栈指针),此时处理器转而执行另一个处于同一进程中或不同进程中的就绪线程
- 解除阻塞:当阻塞一个线程的事件发生时,该线程被转移到就绪队列中
- 结束:当一个线程完成时,其寄存器上下文和栈都被释放
线程的生命周期
3.线程分类
线程的实现可以分为两大类:
- 用户级线程:有关线程管理的所有工作都由应用程序完成(使用线程库),内核意识不到线程的存在
- 内核级线程:有关线程管理的所有工作都由内核完成,应用程序部分没有进行线程管理的代码
3.1 用户级线程
在用户级线程中,进程和线程的状态可能有如下转换:
- a)->b):线程2中执行的应用程序代码进行系统调用,阻塞了进程B。例如,进行一次I/O调用。这导致控制转移到内核,内核启动I/O操作,把进程B置于阻塞状态,并切换到另一个进程。在此期间,根据线程库维护的数据结构,进程B的线程2仍处于运行状态。值得注意的是,从处理器上执行的角度看,线程2实际上并不处于运行态,但是在线程库看来,它处于运行态
- a)->c):时钟中断把控制传递给内核,内核确定当前正在运行的进程B已经用完了它的时间片。内核把进程B置于就绪态并切换到另一个进程。同时,根据线程库维护的数据结构,进程B的线程2仍处于运行态
- a)->d):线程2运行到需要进程B的线程1执行某些动作的一个点。此时,线程2进入阻塞态,而线程1从就绪态转换到运行态。进程自身保留在运行态
在前两种情况中,当内核把控制切换回进程B时,线程2会恢复执行
还需注意,进程在执行线程库中的代码时可以被中断,或者是由于它的时间片用完了,或者是由于被一个更高优先级的进程所抢占。因此在中断时,进程可能处于线程切换的中间时刻。当该进程被恢复时,线程库得以继续运行,并完成线程切换和把控制转移给另一个线程
用户级线程的优点
- 由于所有线程管理数据结构都在一个进程的用户地址空间中,线程切换不需要内核态特权,节省了两次状态转换的开销
- 调度可以是应用程序相关的(一个应用程序可能更适合简单的轮转调度,另一个可能更适合基于优先级的调度),可以为应用量身定做调度算法而不扰乱底层操作系统调度程序
- 可以在任何操作系统中运行,不需要对底层内核进行修改以支持用户级线程
用户级线程的缺点
- 当用户级线程执行一个系统调用时,不仅这个线程会被阻塞,进程中的所有线程都会被阻塞
- 一个多线程应用程序不能利用多处理技术。内核一次只把一个进程分配给一个处理器,因此一次进程中只有一个线程可以执行(事实上,在一个进程内,相当于实现了应用程序级别的多道程序)
3.2 内核级线程
内核能意识到线程的存在
内核级线程的优点
- 内核可以同时把同一进程中的多个线程调度到多个处理器中同时运行
- 如果进程中一个线程被阻塞,内核可以调度其它线程
- 内核例程自身也可以使用多线程
内核级线程的缺点
- 把控制从一个线程转移到用一进程的另一线程时,需要到内核的状态切换
3.3 混合方案
可以混合使用用户级和内核级线程。在混合方案中,同一应用程序中的多个线程可以在多个处理器上并行地运行,某个会引起阻塞的系统调用不会阻塞整个进程。
如果设计正确,该方法将会结合纯粹用户级线程和内核级线程方法的优点,同时克服它们的缺点
|