2.1.6线程和多线程模型
1.线程的基本槪念
引入进程的目的是更好地使多道程序并发执行,提高资源利用率和系统吞吐量;而引入线程 的目的则是减小程序在并发执行时所付出的时空开销,提高操作系统的并发性能。
线程最直接的理解就是“轻量级进程”,它是一个基本的CPU执行单元,也是程序执行流的 最小单元,由线程ID、程序计数器、寄存器集合和堆栈组成。线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其他线程共享进程所拥有的全部资源。一个线程可以创建和撤销另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。
引入线程后,进程的内涵发生了改变,进程只作为除CPU外的系统资源的分配单元,而线 程则作为处理机的分配单元。由于一个进程内部有多个线程,若线程的切换发生在同一个进程内部,则只需要很少的时空开销。下面从几个方面对线程和进程进行比较。
2. 线程与进程的比较
1) 调度。在传统的操作系统中,拥有资源和独立调度的基本单位都是进程,每次调度都要 进行上下文切换,开销较大。在引入线程的操作系统中,线程是独立调度的基本单位, 而线程切换的代价远低于进程。在同一进程中,线程的切换不会引起进程切换。但从一个进程中的线程切换到另一个进程中的线程时,会引起进程切换。
2) 并发性。在引入线程的操作系统中,不仅进程之间可以并发执行,而且一个进程中的多 个线程之间亦可并发执行,甚至不同进程中的线程也能并发执行,从而使操作系统具有 更好的并发性,提高了系统资源的利用率和系统的吞吐量。
3) 拥有资源。进程是系统中拥有资源的基本单位,而线程不拥有系统资源(仅有一点必不 可少、能保证独立运行的资源),但线程可以访问其隶属进程的系统资源,这主要表现在 属于同一进程的所有线程都具有相同的地址空间。要知道,若线程也是拥有资源的单位, 则切换线程就需要较大的时空开销,线程这个概念的提出就没有意义。
4) 独立性。每个进程都拥有独立的地址空间和资源,除了共享全局变量,不允许其他进程 访问。某进程中的线程对其他进程不可见。同一进程中的不同线程是为了提高并发性及进行相互之间的合作而创建的,它们共享进程的地址空间和资源。
5) 系统开销。在创建或撤销进程时,系统都要为之分配或回收进程控制块PCB及其他资源, 如内存空间、I/O设备等。操作系统为此所付出的开销,明显大于创建或撤销线程时的开销。类似地,在进程切换时涉及进程上下文的切换,而线程切换时只需保存和设置少量寄存器内容,开销很小。此外,由于同一进程内的多个线程共享进程的地址空间,因此这些线程之间的同步与通信非常容易实现,甚至无须操作系统的干预。
6) 支持多处理机系统。对于传统单线程进程,不管有多少处理机,进程只能运行在一个处 理机上。对于多线程进程,可以将进程中的多个线程分配到多个处理机上执行。
3. 线程的属性
多线程操作系统中的进程已不再是一个基本的执行实体,但它仍具有与执行相关的状态。所谓进程处于“执行”状态,实际上是指该进程中的某线程正在执行。线程的主要属性如下:
1) 线程是一个轻型实体,它不拥有系统资源,但每个线程都应有一个唯一的标识符和一个 线程控制块,线程控制块记录了线程执行的寄存器和栈等现场状态。
2) 不同的线程可以执行相同的程序,即同一个服务程序被不同的用户调用时,操作系统把 它们创建成不同的线程。
3) 同一进程中的各个线程共享该进程所拥有的资源。
4) 线程是处理机的独立调度单位,多个线程是可以并发执行的。在单CPU的计算机系统中, 各线程可交替地占用CPU;在多CPU的计算机系统中,各线程可同时占用不同的CPU, 若各个CPU同时为一个进程内的各线程服务,则可缩短进程的处理时间。
5) 一个线程被创建后,便开始了它的生命周期,直至终止。线程在生命周期内会经历阻塞 态、就绪态和运行态等各种状态变化。
为什么线程的提出有利于提高系统并发性?可以这样来理解:由于有了线程,线程切换时, 有可能会发生进程切换,也有可能不发生进程切换,平均而言每次切换所需的开销就变小了,因
此能够让更多的线程参与并发,而不会影响到响应时间等问题。
4.线程的状态与转换
与进程一样,各线程之间也存在共享资源和相互合作的制约关系,致使线程在运行时也具有 间断性。相应地,线程在运行时也具有下面三种基本状态。
执行状态:线程已获得处理机而正在运行。
就绪状态:线程已具备各种执行条件,只需再获得CPU便可立即执行。
阻塞状态:线程在执行中因某事件受阻而处于暂停状态。
线程这三种基本状态之间的转换和进程基本状态之间的转换是一样的。
5. 线程的组织与控制
(1) 线程控制块
与进程类似,系统也为每个线程配置一个线程控制块TCB,用于记录控制和管理线程的信息。 线程控制块通常包括:
①线程标识符;
②一组寄存器,包括程序计数器、状态寄存器和通用寄存器;
③线程运行状态,用于描述线程正处于何种状态;
④优先级;
⑤线程专有存储区,线程切换时用于保存现场等;
⑥堆栈指针,用于过程调用时保存局部变量及返回地址等。
同一进程中的所有线程都完全共享进程的地址空间和全局变量。各个线程都可以访问进程地 址空间的每个单元,所以一个线程可以读、写或甚至清除另一个线程的堆栈。
(2) 线程的创建
线程也是具有生命期的,它由创建而产生,由调度而执行,由终止而消亡。相应地,在操作系统中就有用于创建线程和终止线程的函数(或系统调用)。
用户程序启动时,通常仅有一个称为“初始化线程”的线程正在执行,其主要功能是用于创建新线程。在创建新线程时,需要利用一个线程创建函数,并提供相应的参数,如指向线程主程序的入口指针、堆栈的大小、线程优先级等。线程创建函数执行完后,将返回一个线程标识符。
(3) 线程的终止
当一个线程完成自己的任务后,或线程在运行中出现异常而要被强制终止时,由终止线程调 用相应的函数执行终止操作。但是有些线程(主要是系统线程)一旦被建立,便一直运行而不会 被终止。通常,线程被终止后并不立即释放它所占有的资源,只有当进程中的其他线程执行了分 离函数后,被终止线程才与资源分离,此时的资源才能被其他线程利用。
被终止但尚未释放资源的线程仍可被其他线程调用,以使被终止线程重新恢复运行。
6. 线程的实现方式
线程的实现可以分为两类:用户级线程(User-Level Thread, ULT)和内核级线程(Kernel-Level Thread, KLT)。内核级线程又称内核支持的线程。
(1)用户级线程(ULT)
在用户级线程中,有关线程管理(创建、撤销和切换等)的所有工作都由应用程序在用户空 间中完成,内核意识不到线程的存在。应用程序可以通过使用线程库设计成多线程程序。通常, 应用程序从单线程开始,在该线程中开始运行,在其运行的任何时刻,可以通过调用线程库中的派生例程创建一个在相同进程中运行的新线程。图2.5(a)说明了用户级线程的实现方式。
对于设置了用户级线程的系统,其调度仍是以进程为单位进行的,各个进程轮流执行一个时
间片。假设进程A包含1个用户级线程,进程B包含100个用户级线程,这样,进程A中线程 的运行时间将是进程B中各线程运行时间的100倍,因此对线程来说实质上是不公平的。
这种实现方式的优点如下:
①线程切换不需要转换到内核空间,节省了模式切换的开销。
②调度算法可以是进程专用的,不同的进程可根据自身的需要,对自己的线程选择不同的调度算法。
③用户级线程的实现与操作系统平台无关,对线程管理的代码是属于用户程序的一部分。
这种实现方式的缺点如下:
①系统调用的阻塞问题,当线程执行一个系统调用时,不仅该线 程被阻塞,而且进程内的所有线程都被阻塞。
②不能发挥多处理机的优势,内核每次分配给一个 进程的仅有一个CPU,因此进程中仅有一个线程能执行。
图2.5用户级线程和内核级线程
(2) 内核级线程(KLT)
在操作系统中,无论是系统进程还是用户进程,都是在操作系统内核的支持下运行的,与内核紧密相关。内核级线程同样也是在内核的支持下运行的,线程管理的所有工作也是在内核空间内实现的。内核空间也为每个内核级线程设置一个线程控制块,内核根据该控制块感知某线程的存在,并对其加以控制。图2.5(b)说明了内核级线程的实现方式。
这种实现方式的优点如下:
①能发挥多处理机的优势,内核能同时调度同一进程中的多个线程并行执行。
②如果进程中的一个线程被阻塞,内核可以调度该进程中的其他线程占用处理机, 也可运行其他进程中的线程。
③内核支持线程具有很小的数据结构和堆栈,线程切换比较快、开 销小。
④内核本身也可采用多线程技术,可以提高系统的执行速度和效率。
这种实现方式的缺点如下:同一进程中的线程切换,需要从用户态转到核心态进行,系统开销较大。这是因为用户进程的线程在用户态运行,而线程调度和管理是在内核实现的。
(3) 组合方式
有些系统使用组合方式的多线程实现。在组合实现方式中,内核支持多个内核级线程的建立、 调度和管理,同时允许用户程序建立、调度和管理用户级线程。一些内核级线程对应多个用户级 线程,这是用户级线程通过时分多路复用内核级线程实现的。同一进程中的多个线程可以同时在 多处理机上并行执行,且在阻塞一个线程时不需要将整个进程阻塞,所以组合方式能结合KLT和 ULT的优点,并且克服各自的不足。图2.5(c)展示了这种组合实现方式。
在线程实现方式的介绍中,提到了通过线程库来创建和管理线程。线程库(thread library)
是为程序员提供创建和管理线程的APL实现线程库主要的方法有如下两种:
①在用户空间中提供一个没有内核支持的库。这种库的所有代码和数据结构都位于用户空间中。这意味着,调用库内的一个函数只导致用户空间中的一个本地函数的调用。
②实现由操作系统直接支持的内核级的一个库。对于这种情况,库内的代码和数据结构位于内核空间。调用库中的一个API函数通常会导致对内核的系统调用。
目前使用的三种主要线程库是:POSIX Pthreads> Windows API> JavaoPthreads作为POSIX
标准的扩展,可以提供用户级或内核级的库。Windows线程库是用于Windows操作系统的内核级线程库。Java线程API允许线程在Java程序中直接创建和管理。然而,由于JVM实例通常运行在宿主操作系统之上,Java线程API通常采用宿主系统的线程库来实现,因此在Windows系统中Java线程通常采用Windows API来实现,在类UNIX系统中采用Pthreads 来实现。
7.多线程模型
有些系统同时支持用户线程和内核线程,由于用户级线程和内核级线程连接方式的不同,从 而形成了下面三种不同的多线程模型。
1) 多对一模型。将多个用户级线程映射到一个内核级线程,如图2.6(a)所示。这些用户线程一般属于一个进程,线程的调度和管理在用户空间完成。仅当用户线程需要访问内核时, 才将其映射到一个内核级线程上,但是每次只允许一个线程进行映射。
优点:线程管理是在用户空间进行的,因而效率比较高。
缺点:如果一个线程在访问内核时发生阻塞,则整个进程都会被阻塞;在任何时刻,只 有一个线程能够访问内核,多个线程不能同时在多个处理机上运行。
2) 一对一模型。将每个用户级线程映射到一个内核级线程,如图2.6(b)所示。 优点:当一个线程被阻塞后,允许调度另一个线程运行,所以并发能力较强。缺点:每创建一个用户线程,相应地就需要创建一个内核线程,开销较大。
3) 多对多模型。将"个用户线程映射到加个内核级线程上,要求必加,如图2.6(c)所示。特点:既克服了多对一模型并发度不高的缺点,又克服了一对一模型的一个用户进程占 用太多内核级线程而开销太大的缺点。此外,还拥有上述两种模型各自的优点。
图2.6多线程模型
声明:
(一)由于考试政策等各方面情况的不断调整与变化,本网站所提供的考试信息仅供参考,请以权威部门公布的正式信息为准。
(二)本网站在文章内容来源出处标注为其他平台的稿件均为转载稿,免费转载出于非商业性学习目的,版权归原作者所有。如您对内容、版权等问题存在异议请与本站联系,我们会及时进行处理解决。
相关推荐
2023年4月浙江自考英美文学选读复习笔记:Alfred Tennyson
12-092023年4月浙江自考英美文学选读复习笔记:Washington Irving
12-082022年浙江自考《网络操作系统》复习资料(9)
09-192023年4月浙江自考旅行社经营与管理复习笔记:旅游者购买动机
12-062023年4月浙江自考《中国现代文学作品选》复习资料总结(十三)
01-302023年4月浙江自考心理测验学串讲笔记五
12-192022年浙江自考中国现代文学作品选复习资料:作品主要内容
10-152022年浙江自考心理学复习笔记:人格性质
11-032023年4月浙江自考心理卫生与心理辅导复习笔记:认知重建法
12-262023年10月浙江自考幼儿园组织与管理复习资料:我国幼教行政管理及体制
05-16