共计 5446 个字符,预计需要花费 14 分钟才能阅读完成。
过程和线程的概念
先理解一下操作系统的一些相干概念,大部分操作系统 (如 Windows、Linux) 的任务调度是采纳工夫片轮转的抢占式调度形式,也就是说一个工作执行一小段时间后强制暂停去执行下一个工作,每个工作轮流执行。工作执行的一小段时间叫做工夫片,工作正在执行时的状态叫运行状态,工作执行一段时间后强制暂停去执行下一个工作,被暂停的工作就处于就绪状态期待下一个属于它的工夫片的到来。这样每个工作都能失去执行,因为 CPU 的执行效率十分高,工夫片十分短,在各个工作之间疾速地切换,给人的感觉就是多个工作在“同时进行”,这也就是咱们所说的并发 (并发简略来说多个工作同时执行)。
过程
计算机的外围是 CPU,它承当了所有的计算工作;而操作系统是计算机的管理者,它负责工作的调度、资源的调配和治理,统领整个计算机硬件;应用程序侧是具备某种性能的程序,程序是运行于操作系统之上的。
过程是一个具备肯定独立性能的程序在一个数据集上的一次动静执行的过程,是操作系统进行资源分配和调度的一个独立单位,是利用程序运行的载体。过程是一种形象的概念,素来没有对立的规范定义。过程个别由程序、数据汇合和过程管制块三局部组成。程序用于形容过程要实现的性能,是管制过程执行的指令集;数据汇合是程序在执行时所须要的数据和工作区;程序控制块(Program Control Block,简称 PCB),蕴含过程的形容信息和管制信息,是过程存在的惟一标记。
过程具备的特色:
动态性:过程是程序的一次执行过程,是长期的,有生命期的,是动静产生,动静沦亡的;
并发性:任何过程都能够同其余过程一起并发执行;
独立性:过程是零碎进行资源分配和调度的一个独立单位;
结构性:过程由程序、数据和过程管制块三局部组成。
过程的生命周期
在晚期只有过程的操作系统中,过程有五种状态,创立、就绪、运行、阻塞 (期待)、退出。
创立:过程正在创立,还不能运行。操作系统在创立过程时要进行的工作包含调配和建设过程管制块表项、建设资源表格并分配资源、加载程序并建设地址空间;
就绪:工夫片已用完,此线程被强制暂停,期待下一个属于他的工夫片到来;
运行:此线程正在执行,正在占用工夫片;
阻塞:也叫期待状态,期待某一事件 (如 IO 或另一个线程) 执行完;
退出:过程已完结,所以也称完结状态,开释操作系统调配的资源。
线程
在晚期的操作系统中并没有线程的概念,过程是能领有资源和独立运行的最小单位,也是程序执行的最小单位。任务调度采纳的是工夫片轮转的抢占式调度形式,而过程是任务调度的最小单位,每个过程有各自独立的一块内存,使得各个过程之间内存地址互相隔离。
起初,随着计算机的倒退,对 CPU 的要求越来越高,过程之间的切换开销较大,曾经无奈满足越来越简单的程序的要求了。于是就创造了线程,线程是程序执行中一个繁多的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的根本单位。一个过程能够有一个或多个线程,各个线程之间共享程序的内存空间。
一个规范的线程由线程 ID、以后指令指针 (PC)、寄存器和堆栈组成。而过程由内存空间(代码、数据、过程空间、关上的文件) 和一个或多个线程组成。
线程的生命周期
当线程的数量小于处理器的数量时,线程的并发是真正的并发,不同的线程运行在不同的处理器上。但当线程的数量大于处理器的数量时,线程的并发会受到一些妨碍,此时并不是真正的并发,因为此时至多有一个处理器会运行多个线程。在单个处理器运行多个线程时,并发是一种模仿进去的状态。操作系统采纳工夫片轮转的形式轮流执行每一个线程。当初,简直所有的古代操作系统采纳的都是工夫片轮转的抢占式调度形式,如咱们相熟的 Unix、linux、Windows 及 Mac OS X 等风行的操作系统。
创立:一个新的线程被创立,期待该线程被调用执行;
就绪:工夫片已用完,此线程被强制暂停,期待下一个属于他的工夫片到来;
运行:此线程正在执行,正在占用工夫片;
阻塞:也叫期待状态,期待某一事件 (如 IO 或另一个线程) 执行完;
退出:一个线程实现工作或者其余终止条件产生,该线程终止进入退出状态,退出状态开释该线程所调配的资源。
线程优先级
操作系统 (如 Windows、Linux、Mac OS X) 的任务调度除了具备后面提到的工夫片轮转的特点外,还有优先级调度 (Priority Schedule) 的特点。优先级调度决定了线程依照什么程序轮流执行,在具备优先级调度的零碎中,线程领有各自的线程优先级(Thread Priority)。具备高优先级的线程会更早地执行,而低优先级的线程通常要等没有更高优先级的可执行线程时才会被执行。
线程的优先级能够由用户手动设置,此外零碎也会依据不同情景调整优先级。通常状况下,频繁地进入期待状态 (进入期待状态会放弃之前仍可占用的工夫份额) 的线程(如 IO 线程),比频繁进行大量计算以至于每次都把所有工夫片全副用尽的线程更受操作系统的欢送。因为频繁进入期待的线程只会占用很少的工夫,这样操作系统能够解决更多的工作。咱们把频繁期待的线程称之为 IO 密集型线程(IO Bound Thread),而把很少期待的线程称之为 CPU 密集型线程(CPU Bound Thread)。IO 密集型线程总是比 CPU 密集型线程更容易失去优先级的晋升。
线程饿死
在优先级调度下,容易呈现一种线程饿死的景象。一个线程饿死是说它的优先级较低,在它执行之前总是有比它优先级更高的线程期待执行,因而这个低优先级的线程始终得不到执行。当 CPU 密集型的线程优先级较高时,其它低优先级的线程就很可能呈现饿死的状况;当 IO 密集型线程优先级较高时,其它线程绝对不容易造成饿死的,因为 IO 线程有大量的等待时间。为了防止线程饿死,调度零碎通常会逐渐晋升那些期待了很久而得不到执行的线程的优先级。这样,一个线程只有它期待了足够长的工夫,其优先级总会被晋升到能够让它执行的水平,也就是说这种状况下线程始终会失去执行,只是工夫的问题。
在优先级调度环境下,线程优先级的扭转有三种形式:
1. 用户指定优先级;
2. 依据进入期待状态的频繁水平晋升或升高优先级(由操作系统实现);
3. 长时间得不到执行而被晋升优先级。
多线程与多核
下面提到的工夫片轮转的调度形式说一个工作执行一小段时间后强制暂停去执行下一个工作,每个工作轮流执行。很多操作系统的书都说“同一时间点只有一个工作在执行”。其实“同一时间点只有一个工作在执行”这句话是不精确的,至多它是不全面的。咱们剖析一下多核的状况。
这是我的电脑的 CPU 状况图:
多核 (心) 处理器是指在一个处理器上集成多个运算外围从而进步计算能力,也就是有多个真正并行计算的解决外围,每一个解决外围对应一个内核线程。内核线程(Kernel Thread,KLT)就是间接由操作系统内核反对的线程,这种线程由内核来实现线程切换,内核通过操作调度器对线程进行调度,并负责将线程的工作映射到各个处理器上。个别一个解决外围对应一个内核线程,比方单核处理器对应一个内核线程,双核处理器对应两个内核线程,四核处理器对应四个内核线程。
当初的电脑个别是双核四线程、四核八线程,是采纳超线程技术将一个物理解决外围模仿成两个逻辑解决外围,对应两个内核线程,所以在操作系统中看到的 CPU 数量是理论物理 CPU 数量的两倍。然而我的如上图是四核四线程,仿佛没有用这个超线程技术。
超线程技术就是利用非凡的硬件指令,把一个物理芯片模仿成两个逻辑解决外围,让单个处理器都能应用线程级并行计算,进而兼容多线程操作系统和软件,缩小了 CPU 的闲置工夫,进步的 CPU 的运行效率。这种超线程技术 (如双核四线程) 由处理器硬件的决定,同时也须要操作系统的反对能力在计算机中体现进去。
程序个别不会间接去应用内核线程,而是去应用内核线程的一种高级接口——轻量级过程(Light Weight Process,LWP),轻量级过程就是咱们通常意义上所讲的线程(咱们在这称它为用户线程),因为每个轻量级过程都由一个内核线程反对,因而只有先反对内核线程,能力有轻量级过程。用户线程与内核线程的对应关系有三种模型:一对一模型、多对一模型、多对多模型,在这以 4 个内核线程、3 个用户线程为例对三种模型进行阐明。
一对一模型
对于一对一模型来说,一个用户线程就惟一地对应一个内核线程(反过来不肯定成立,一个内核线程不肯定有对应的用户线程)。这样,如果 CPU 没有采纳超线程技术(如四核四线程的计算机,就如上图展现的我应用的计算机),一个用户线程就惟一地映射到一个物理 CPU 的线程,线程之间的并发是真正的并发。一对一模型使用户线程具备与内核线程一样的长处,一个线程因某种原因阻塞时其余线程的执行不受影响;此处,一对一模型也能够让多线程程序在多处理器的零碎上有更好的体现。但一对一模型也有两个毛病:
1. 许多操作系统限度了内核线程的数量,因而一对一模型会使用户线程的数量受到限制;
2. 许多操作系统内核线程调度时,上下文切换的开销较大,导致用户线程的执行效率降落。
多对一模型
多对一模型将多个用户线程映射到一个内核线程上,线程之间的切换由用户态的代码来进行,因而绝对一对一模型,多对一模型的线程切换速度要快许多;此外,多对一模型对用户线程的数量简直无限度。但多对一模型也有两个毛病:
1. 如果其中一个用户线程阻塞,那么其它所有线程都将无奈执行,因为此时内核线程也随之阻塞了;
2. 在多处理器零碎上,处理器数量的减少对多对一模型的线程性能不会有显著的减少,因为所有的用户线程都映射到一个处理器上了。
多对多模型
多对多模型联合了一对一模型和多对一模型的长处,将多个用户线程映射到多个内核线程上。多对多模型的长处有:
1. 一个用户线程的阻塞不会导致所有线程的阻塞,因为此时还有别的内核线程被调度来执行;
2. 多对多模型对用户线程的数量没有限度;
3. 在多处理器的操作系统中,多对多模型的线程也能失去肯定的性能晋升,但晋升的幅度不如一对一模型的高。
过程与线程的区别
- 线程是程序执行的最小单位,而过程是操作系统分配资源的最小单位;
- 一个过程由一个或多个线程组成,线程是一个过程中代码的不同执行路线;
- 过程之间互相独立,但同一过程下的各个线程之间共享程序的内存空间 (包含代码段、数据集、堆等) 及一些过程级的资源(如关上文件和信号),某过程内的线程在其它过程不可见;
- 调度和切换:线程上下文切换比过程上下文切换要快得多。
总之,线程和过程都是一种形象的概念,线程是一种比过程更小的形象,线程和过程都可用于实现并发。
在晚期的操作系统中并没有线程的概念,过程是能领有资源和独立运行的最小单位,也是程序执行的最小单位。它相当于一个过程里只有一个线程,过程自身就是线程。所以线程有时被称为轻量级过程(Lightweight Process,LWP)。
起初,随着计算机的倒退,对多个工作之间上下文切换的效率要求越来越高,就形象出一个更小的概念——线程,个别一个过程会有多个 (也可是一个) 线程。
漫话过程和线程
1. 计算机的外围是 CPU,它承当了所有的计算工作。它就像一座工厂,时刻在运行。
2. 假设工厂的电力无限,一次只能供应一个车间应用。也就是说,一个车间动工的时候,其余车间都必须复工。背地的含意就是,单个 CPU 一次只能运行一个工作。
3. 过程就好比工厂的车间,它代表 CPU 所能解决的单个工作。任一时刻,CPU 总是运行一个过程,其余过程处于非运行状态。
4. 一个车间里,能够有很多工人。他们协同实现一个工作。
5. 线程就好比车间里的工人。一个过程能够包含多个线程。
6. 车间的空间是工人们共享的,比方许多房间是每个工人都能够进出的。这象征一个过程的内存空间是共享的,每个线程都能够应用这些共享内存。
7. 可是,每间房间的大小不同,有些房间最多只能包容一个人,比方厕所。外面有人的时候,其他人就不能进去了。这代表一个线程应用某些共享内存时,其余线程必须等它完结,能力应用这一块内存。
8. 一个避免别人进入的简略办法,就是门口加一把锁。先到的人锁上门,后到的人看到上锁,就在门口排队,等锁关上再进去。这就叫”互斥锁”(Mutual exclusion,缩写 Mutex),避免多个线程同时读写某一块内存区域。
9. 还有些房间,能够同时包容 n 集体,比方厨房。也就是说,如果人数大于 n,多进去的人只能在里面等着。这好比某些内存区域,只能供应固定数目的线程应用。
10. 这时的解决办法,就是在门口挂 n 把钥匙。进去的人就取一把钥匙,进去时再把钥匙挂回原处。后到的人发现钥匙架空了,就晓得必须在门口排队等着了。这种做法叫做”信号量”(Semaphore),用来保障多个线程不会互相冲突。
不难看出,mutex 是 semaphore 的一种非凡状况(n= 1 时)。也就是说,齐全能够用后者代替前者。然而,因为 mutex 较为简单,且效率高,所以在必须保障资源独占的状况下,还是采纳这种设计。
操作系统的设计,因而能够归结为三点:
(1)以多过程模式,容许多个工作同时运行;
(2)以多线程模式,容许单个工作分成不同的局部运行;
(3)提供协调机制,一方面避免过程之间和线程之间产生抵触,另一方面容许过程之间和线程之间共享资源。
作者:Luckylau
地址:http://r6d.cn/6mKF
欢送关注我的微信公众号「码农解围」,分享 Python、Java、大数据、机器学习、人工智能等技术,关注码农技术晋升•职场解围•思维跃迁,20 万 + 码农成长充电第一站,陪有幻想的你一起成长