CPU线程调度了解

算法概念

假设计算机只有一个 CPU ,则在任意时刻只能执行一条机器指令,每个线程只有获得 CPU 的使用权才能执行指令。

  • 所谓多线程的并发运行,其实是指从宏观上看,各个线程轮流获得 CPU 的使用权,分别执行各自的任务。
  • 在运行池中,会有多个处于就绪状态的线程在等待 CPU ,Java 虚拟机的一项任务就是负责线程的调度,线程调度是指按照特定机制为多个线程分配 CPU 的使用权。

 

有两种调度模型:分时调度模型抢占式调度模型

  • 分时调度模型是指让所有的线程轮流获得 CPU 的使用权,并且平均分配每个线程占用的 CPU 的时间片这个也比较好理解。 。
  • Java 虚拟机采用抢占式调度模型,是指优先让可运行池中优先级高的线程占用 CPU ,如果可运行池中的线程优先级相同,那么就随机选择一个线程,使其占用 CPU 。处于运行状态的线程会一直运行,直至它不得不放弃CPU 。

(用户空间和内核空间)

线程饥饿概念

饥饿,一个或者多个线程因为种种原因无法获得所需要的资源,导致一直无法执行的状态。

Java 中导致饥饿的原因:

  • 高优先级线程吞噬所有的低优先级线程的 CPU 时间。
  • 线程被永久堵塞在一个等待进入同步块的状态,因为其他线程总是能在它之前持续地对该同步块进行访问。
  • 线程在等待一个本身也处于永久等待完成的对象(比如调用这个对象的 wait 方法),因为其他线程总是被持续地获得唤醒。

 

线程优化级概念

每一个线程都是有优先级的,一般来说,高优先级的线程在运行时会具有优先权,但这依赖于线程调度的实

现,这个实现是和操作系统相关的(OS dependent)

  • 我们可以定义线程的优先级,但是这并不能保证高优先级的线程会在低优先级的线程前执行。线程优先级是一个 int 变量(从1-10),1 代表最低优先级,10 代表最高优先级。
  • Java 的线程优先级调度会委托给操作系统去处理,所以与具体的操作系统优先级有关,如非特别需要,一般无需设置线程优先级。

 

进程

概念

计算机的核心是CPU,它承担了所有的计算任务,而操作系统是计算机的管理者,它负责任务的调度,资源的分配和管理,统领整个计算机硬件;应用程序是具有某种功能的程序,程序是运行于操作系统之上的。

 

进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体。进程是一种抽象的概念,从来没有统一的标准定义。

 

进程一般由程序,数据集合和进程控制块三部分组成。

  • 程序用于描述进程要完成的功能,是控制进程执行的指令集
  • 数据集合是程序在执行时所需要的数据和工作区
  • 程序控制块包含进程的描述信息是进程存在的唯一标志。

进程具有的特征:

动态性:进程是程序的一次执行过程,是临时的,有生命期的,是动态产生,动态消亡的;

并发性:任何进程都可以同其他进程一起并发执行;

独立性:进程是系统进行资源分配和调度的一个独立单位;

结构性:进程由程序,数据和进程控制块三部分组成。

 

线程

概念

在早期的操作系统中并没有线程的概念,进程是拥有资源和独立运行的最小单位,也是程序执行的最小单位。任务调度采用的是时间片轮转的抢占式调度方式,而进程是任务调度的最小单位,每个进程有各自独立的一块内存,使得各个进程之间内存地址相互隔离。

后来随着计算机的发展,对CPU的要求越来越高,进程之间的切换开销较大,已经无法满足越来越复杂的程序的要求了。于是就发明了线程,线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。一个进程可以有一个或多个线程各个线程之间共享程序的内存空间(也就是所在进程的内存空间)。一个标准的线程由线程ID,当前指令指针PC,寄存器和堆栈组成。

而进程由内存空间(代码,数据,进程空间,打开的文件)和一个或多个线程组成。

 

线程生命状态

NEW--新建

RUNNABLE--运行

BLOCKED--阻塞

WAITTING--等待

TIMED_WAITTING--超时等待

TERMINATED--终结

 

生命周期

协程

概念

协程是一种用户级的轻量级线程,一个线程可以有0到多个协程,协程本质是一个线程时间分片去执行协程代码段。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。

 

同一进程中,在多CPU的环境中,多线程可以并行,即多个线程同时在运行。

同一线程中,多协程只能并发,即同一时间只有一个协程在运行。

 

优点:

(1) 协程的执行效率非常高。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。

(2)协程不需要多线程的锁机制。在协程中控制共享资源不加锁,只需要判断状态就好了

 

线程模型

参考

线程模型概念

概念

线程是CPU调度的最小单位,可以独立的完成任务;进程是资源拥有的基本单位。

在同一进程中,线程的切换不会引起进程切换。

在不同进程中进行线程切换,如从一个进程内的线程切换到另一个进程中的线程时,会引起进程切换

根据操作系统内核是否对线程可感知,可以把线程分为内核线程和用户线程

而操作系统中想要实现多线程,主要使用3种多线程模型:

● 内核线程模型

● 用户线程模型

● 混合线程模型


内核线程模型

Kernel-Level Thread 简称KLT,内核线程模型完全依赖于操作系统内核,内核保存线程的状态和信息,线程的创建、调度和管理由内核完成,并且系统内核负责将多个线程执行的任务映射到各个CPU中去执行。

线程管理的所有工作由内核完成,应用程序没有进行线程管理的代码,只有一个到内核级线程的编程接口. 内核为进程及其内部的每个线程维护上下文信息,调度也是在内核基于线程架构的基础上完成。每个用户线程都直接与一个内核线程相关联

 

内核线程的优点:

  1. 多处理器系统中,内核能够并行执行同一进程内的多个线程
  2. 如果进程中的一个线程被阻塞,能够切换同一进程内的其他线程继续执行(用户级线程的一个缺点)
  1. 所有能够阻塞线程的调用都以系统调用的形式实现,代价可观

 

内核线程的缺点:

各种线程的操作都需要在用户态和内核态之间频繁切换,消耗太大,速度相对用户线程模型来说要慢。

 

用户线程模型

User-Level Thread 简称ULT,用户线程模型不依赖操作系统核心,应用提供创建、同步、调度和管理线程函数来控制用户线程。不需要线程从用户态到内核态切换,速度快。

用户级线程仅存在于用户空间中,此类线程的创建、撤销、线程之间的同步与通信功能,都无须利用系统调用来实现。用户进程利用线程库来控制用户线程(如JAVA调用PThread库)。用户级线程是一种”多对一”的线程映射

 

优点:线程的各种操作以及切换消耗很低;

缺点:线程的所有操作都需要在用户态实现,线程的调度实现起来异常复杂,并且系统内核对ULT无感知,如果线程阻塞则会引起整个进程的阻塞。

 

组合线程模型

组合线程模型是内核线程和用户线程的混合使用,用户线程仍然是在用户态中创建,用户线程的创建、切换和销毁的消耗很低,用户线程的数量不受限制。而LWP在用户线程和内核线程之间充当桥梁,就可以使用操作系统提供的线程调度和处理器映射功能。

 

posted @ 2021-07-15 23:13  Flyinglion  阅读(1286)  评论(1编辑  收藏  举报