操作系统---线程(一)

进程模型假设进程是一个具有单个控制线程的执行程序。现在许多线性操作系统都提供单个进程包含多个控制线程的特征。本章引入了与多线程计算机系统相关的概念,包括有关Pthread API 和 Java线程的讨论。
5.1 概述 线程, 有时称为 轻量级进程(lightweight process, LWP),是CPU使用的基本单位;它由线程ID、进程计数器、寄存器集合和堆栈组成。它与属于同一进程的其他线程共享其代码段、数据段和其他操作系统资源(如打开文件和信号)。一个传统(或重量级(heavyweight)进程)只有单个控制线程。如果进程有多个控制线程,那么它能同时做多个任务。下面图是传统单线程进程和 现代多线程进程之间的差别。
操作系统---线程(一)
文章图片

图5.1 单线程进程和多线程进程
5.1.1 动机 运行在现代桌面个人计算机上的许多软件包都是多线程的(multithreaded)的。一个应用程序通常实现得像一个具有多个控制线程的独立进程。网页浏览器可能有一个线程显示图像或文本,另一个线程从网络接收数据。字处理器可能有一个线程用于显示图形,另一个线程用以读入用户的键盘输入,还有第三线程在后台拼写和语法检查。
某些情况下,一个单独的应用程序可能需要执行多个相似任务。例如, 网页服务器接收用户关于网页、图像、声音等的请求。一个忙碌的网页服务器可能有多个(可能数百个)客户并发访问它。如果网页服务器作为传统单个线程(single-threaded)的进程来执行,那么只能一次对一个客户服务。这样,客户必须等待处理请求的时间可能会很长。
一个解决方案是让服务器作为单个运行来接收请求。当服务器收到请求时,它会创建另一个进程来处理请求。事实上, 这种进程创建方法在线程流行之前很常用。如上一章所述,进程创建特别麻烦。如果新进程与现有进程执行同样的任务,那么为什么需要所有这些开销呢?如果一个具有多个线程的进程能达到同样的目的,那么将更为有效。这种方案要求网页服务器进程是多线程的。服务器创建一个独立线程以监听客户请求;当有请求产生时,服务器不是创建另一个进程而是创建另一个线程以处理请求。
线程在远程过程调用(RPC)系统中也有很重要的作用。RPC通过提供一种类似于普通函数或子程序调用的通信机制,来允许进程间通信。通常,RPC服务器是多线程的。当一个服务器接收到消息,它通过使用独立线程来处理消息。这允许服务器能处理多个并发请求。
5.1.2 优点 多线程编程具有如下四类主要优点:
1、响应度高: 如果对一个交互式应用程序采用多线程,即使其部分阻塞或执行较冗长的操作,那么该程序仍能继续执行,从而增加了对用户的响应程度。例如,多线程网页浏览器在用一个线程装入图像时, 能通过另一个线程与用户交互。
2、资源共享:线程默认共享它们所属进程的内存和资源。代码共享的优点是它能允许一个应用程序在同一地址空间内有多个不同的活动线程。
3、经济:进程创建所需要的内存和资源的分配比较昂贵。不过,由于线程能共享它们所属进程的资源,所以线程创建和上下文切换会更为经济。如果要实际地测量进程创建和维护开销(而非线程开销)的差别,则较为困难;但是前者通常更比后者花费更多的时间。对于Solaris 2,,进程创建要比线程创建慢30倍,而进程上下文切换要比线程上下文切换慢5倍。
4.多处理器体系结构的利用: 多线程的优点之一是能允许使用多处理器体系结构,以便每个线程能并行运行在不同的处理器上。不管有多少CPU,单线程进程只能运行在一个CPU上。在多个CPU机器上使用多线程增加了并发功能。对于单处理器体系结构,CPU通常在线程之间快速移动以创建并行执行的假象,但是实际上在一个时候只能运行一个线程。
5.1.3 用户线程和内核线程 有两种不同方法可用来提供线程支持:用户层的 用户线程 或 内核层的 内核线程。

  • 用户线程 在内核之上支持,并在用户层通过线程库来实现。线程库提供对线程创建、调度和管理的支持而无需内核支持。由于内核并不知道用户级的线程,所以所有线程的创建和调度是在用户空间内进行的,而无需内核干预。因此,用户级线程 通常能快速地创建和管理;但是它们也有缺点。例如,如果内核是单线程的,那么任何一个用户级线程若执行阻塞系统调用就会引起整个进程阻塞,即使还有其他线程可以在应用程序内运行。用户级线程程序包括 POSIX PThread、Mach C-Thread 和 Solaris 2 UI-Thread。
  • 内核线程由操作系统直接支持:内核在其空间内执行线程创建、调度和管理。 因为线程管理是由操作系统完成的,所以内核线程的创建和管理通常要慢于用户线程的创建和管理。不过,由于内核管理线程,当一个线程执行阻塞系统调用时,内核能调度应用程序内的另一个线程以便执行。而且,在多处理器环境下,内核能在不同处理器上调度线程。绝大多数当代操作系统,都支持内核线程。
5.2 多线程模型 许多系统都提供对用户和内核线程的支持,从而有不同的多线程模型。
5.2.1 多对一模型 多对一模型(图5.2) 将许多用户级线程映射到一个内核线程。线程管理是在用户空间进行的,因而效率比较高,但是如果一个线程执行了阻塞系统调用,那么整个进程就会阻塞。而且,因为任一时刻只有一个线程能访问 内核,多个线程不能并行运行在多处理器上。 Green threads ,Solaris 2所提供的线程库,就使用了这种模型。另外, 在不支持内核即线程的操作系统上所实现的用户级线程库也使用了多对一模型。
操作系统---线程(一)
文章图片

图 5.2 多对一模型
5.2.2 一对一模型 一对一模型将每个用户线程映射到一个内核线程。该模型在一个线程执行阻塞系统调用时,能允许另一个线程继续执行,所以它提供了比多对一模型更好的并发功能;它也允许多个线程能并行地运行在多处理器系统上。这种模型的唯一缺点是创建一个用户线程就需要创建一个相应的内核线程。由于创建内核线程的开销会影响应用程序的性能,所以这种模型的绝大多数实现限制了系统所支持的线程数量。
操作系统---线程(一)
文章图片

图5.3 一对一模型
5.2.3 多对多模型 【操作系统---线程(一)】多对多模型(图5.4)多路复用了许多用户级线程到同样数量或更小数量的内核线程上。内核线程的数量可能与特定应用程序或特定机器有关(位于多处理器上的应用程序可比单处理器上的应用程序分配更多数量的内核线程)。虽然多对一模型允许开发人员随意创建任意多的用户线程,但是由于内核只能一次调度一个线程,所以并不能增加并发性。一对一模型提供了更大的并发性,但是开发人员必须小心不要在应用程序内创建太多的线程(在有些情况下可能受她所能创建的线程数量的限制)。多对多模型没有这两者的缺点: 开发人员可创建任意多的必须用户线程,并且相应内核线程能在多处理器系统上并发执行。而且,当一个线程执行阻塞系统调用时,内核能调用另一个线程来执行。
操作系统---线程(一)
文章图片

    推荐阅读