线程
自从60年代提出进程以来,在操作系统中一直都是以进程作为能独立运行的基本单位。直到80年代,人们又提出了比进程更小的运行单位–线程(Thread),用来提高系统内程序并发执行速度,减少系统开销,从而进一步提高系统吞吐量。
近几年线程概念已得到了广泛应用,不仅在新推出的操作系统中,大都引入了线程概念,而且在新推出的数据库管理系统和其他应用软件中,也都采用多线程技术来改善系统性能。
1、线程的引入
在操作系统中引入进程的目的,是为了使多个程序并发执行,以改善资源利用率以及提高系统吞吐量。
而在操作系统中再引入线程则是为了减少程序并发执行时所付出的时空开销,使得操作系统并发粒度更小,并发性更好。
进程的局限性:
进程是操作系统资源分配和调度执行的基本单位,一个能独立运行的实体。然而程序能并发执行,系统还需要进行进程的创建、撤销、切换。
- 系统在创建进程时,必须为之分配其所需的除CPU以外的所有资源,以及建立相应的PCB。
- 系统在撤销进程时,又必须对这些资源进行回收操作,然后再撤销PCB。
- 在对进程进行切换时,由于要保留当前进程的CPU环境和设置新选中进程的CPU环境,为此必须花费很多CPU时间。
总之,进程是一个资源拥有者,因而再进程的创建、撤销、切换中,系统必须为之付出较大的时间空间开销。正因如此,在系统中设置的进程数不宜过多,进程切换的频率也不宜过高,但这也就限制了并发程度的进一步提高。
线程概念的产生:
为了使多个程序能更好地并发执行,同时又减少系统的开销,要把CPU调度和资源分配针对不同的活动实体进行,使之轻装运行,而对拥有资源的基本单位,又不能频繁调地进行切换。正是这种思想指导下产生了线程概念。
CRE:总结:进程是拥有资源的基本单位,而线程是CPU调度的基本单位。
补充:
线程是操作系统进程中能够独立执行的实体(控制流),是处理器调度和分派的基本单位。线程是进程的组成部分,线程只拥有一些在运行中必不可少的资源(例如程序计数器、一组寄存器和栈),与同属一个进程的其他线程共享进程所拥有的全部资源。
一个线程可以创建和撤销另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,导致线程在运行中也呈现间断性。相应地,线程也同样拥有就绪、阻塞、执行三种基本状态,有的系统中线程还有终止状态。
线程也有一一对应的描述和控制数据结构-Thread Control Block。
不同进程间的线程互不可见。同一进程内的线程间通信主要靠全局变量。
2、线程和进程的区别与联系
线程具有许多传统进程所具有的特征,所以又称为轻型进程或进程元,而把传统进程称为重型进程,它相当于只有一个线程的任务。在引入线程的操作系统中,通常一个进程都有若干个线程,至少需要有一个主线程。
- 线程环境背景下对进程再定义:
进程是操作系统中除处理器外的资源分配和保护的基本单位,它有一个独立的虚拟地址空间,用来容纳进程映像(如与进程关联的程序和数据),并以进程为单位对各种资源实施保护,如受保护地访问处理器、文件、外设、其他进程。
- 调度的基本单位和拥有资源的基本单位:
在传统操作系统中,拥有资源的基本单位和独立调度的基本单位都是进程。在引入线程的操作系统中,则把线程作为调度分配基本单位,而把进程作为拥有资源的基本单位。
- 线程切换和进程切换:
在同一进程中,线程的切换不会引起进程的切换;再有一个进程中的线程切换到另一个进程中的线程时,会引起进程切换。
- 并发性:
在引入线程的操作系统中,不仅进程可以并发执行,而且在一个进程中的多个线程也可以并发执行,因此操作系统具有更好的并发性,而从提高系统效率。
- 拥有资源:
无论传统系统还是支持线程的系统,进程都是拥有资源的独立单位,拥有自己的资源。一般来说,线程自己不拥有系统资源(除了一些必不可少的资源),但是可以访问、共享所属进程的资源,包括代码段、数据段、打开的文件、I/O设备等。
- 创建和撤销以及切换:
创建和撤销进程时,操作系统的开销显著大于创建和撤销线程时的开销。进程切换的开销也大于线程切换的开销。
在进行进程切换时涉及当前进程整个CPU环境的保存以及新被调度运行的进程的CPU环境的设置;而线程的切换只需保存和设置少量寄存器内容,并不涉及存储器管理方面的操作。
- 通信:
由于同一进程中的多个线程具有相同的地址空间,致使它们之间的同步和通信的实现也容易。
在有的系统中,线程切换、同步、通信都无须操作系统内核干预。
3、线程的三种模式
线程的实现有三种方式。
内核级线程:
在操作系统内核实现的内核级线程(Kernel Level Thread, KLT),如Windows、OS/2等。线程管理的全部工作由操作系统内核在内核空间实现。系统为应用开发使用内核级线程提供了API,除了API函数调用外,应用程序不需要编写任何线程管理的其他代码。而是通过API实现线程创建和控制管理。
当应用程序执行时,内核根据应用程序中的函数调用完成相应的线程创建和控制管理。
内核为整个进程和进程中的所有线程维护现场信息。
内核建立和维护PCB、TCB,内核的调度是在线程的基础上进行的。
- 优点:
多处理器上,内核能够同时调度同一进程的多个线程并行执行;
如果进程中的一个线程阻塞,内核能够调度同一进程的其他线程占有处理器;
内核级线程的数据结构和堆栈都较小,内核级线程的切换块,提高了处理器效率;
内核级线程自身可以用多线程技术实现,提高了系统并行度和执行速度。
- 缺点:
应用程序的线程运行在用户空间,而线程调度和管理在内核空间,即使是同一进程内运行,当对线程的控制需要从一个线程传送到另一个线程时,也要经过用户态到内核态,再从内核态到用户态的模式切换,系统开销大。
用户级线程:
在用户空间实现的用户级线程(User Level Thead, ULT),如Java的线程库等。线程管理的全部工作由应用程序在用户空间实现,内核不知道线程存在。用户级线程由用户空间运行的用户级线程库实现,应用开发通过线程库实现程序设计,用户级线程库是线程运行的支撑环境。
- 优点:
线程切换不需要内核特权方式,应用开发可自主选择调度算法,能够运行在任何操作系统上。
- 缺点:
如果一个线程被阻塞,则该线程所在进程的所有线程都将被阻塞,不能选择进程的其他线程运行,使处理器处于空闲,浪费了处理器资源;
系统在进程调度时分配给进程的处理器时间需要由所有线程分享,如果系统有多个处理器,也不能实现在一个进程中的线程并行执行。
混合式线程:
同时支持两种线程的混合式线程,例如Solaris系统。
设计恰当,混合式线程既可以具备内核级线程实现的优点,又可以具备用户级线程实现的优点。
- 用户级线程和内核级线程之间的关系可以有三种模型表示:
- 一对一模型 –每创建一个用户级线程,就用创建一个核心级线程与之对应,可以实现多个线程并行执行,但开销大,在实现中应该限制系统的线程数。(Windows和OS/2都实现了这类模型)
- 多对一模型 –将多个用户级线程映射到一个内核级线程,效率较高,但一个线程阻塞会阻塞整个进程,在现实中线程不能实现真正并发。
- 多对多模型 –将多个用户级线程映射到多个内核级线程,但是为了节约系统资源,与用户级线程对应的内核级线程不会超过用户级线程数。吸取了多对一和一对一模型的优点,克服了它们的缺点。(Solaris、Digital UNIX、IRIX操作系统都支持多对多模型)
(END)