进程

进程就是应用程序在内存中分配的空间,也就是正在运行的程序,各个进程之间互不干扰。同时进程保存着程序每一个时刻运行的状态。

CPU采用时间片轮转的方式运行进程:CPU为每个进程分配一个时间段,称作它的时间片。如果在时间片结束时进程还在运行,则暂停这个进程的运行,并且CPU分配给另一个进程(这个过程叫做上下文切换)。如果进程在时间片结束前阻塞或结束,则CPU立即进行切换,不用等待时间片用完。

进程让操作体统的并发成为了可能

线程

让一个线程执行一个子任务,这样一个进程就包含了多个线程,每个线程负责一个单独的子任务。

一个进程虽然包括多个线程,但是这些线程是共同享有进程占有的资源和地址空间的。

线程从属于进程,是程序的实际执行者。一个进程至少包含一个主线程,也可以有更多的子线程。线程拥有自己的栈空间。

Java 中线程具有五种状态:初始化、可运行、运行中、阻塞、销毁。

image-20201216164502646.png

但是,线程不同状态之间的转化是谁来实现的呢?是JVM吗?并不是。JVM需要通过操作系统内核中的TCB(Thread Control Block)模块来改变线程的状态,这一过程需要耗费一定的CPU资源。

CPU通过为每个线程分配CPU时间片来实现多线程机制。CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务。

但是,在切换前会保存上一个任务的状态,以便下次切换回这个任务时,可以再加载这个任务的状态。所以任务从保存到再加载的过程就是一次上下文切换。

上下文切换通常是计算密集型的,意味着此操作会消耗大量的 CPU 时间,故线程也不是越多越好。如何减少系统中上下文切换次数,是提升多线程性能的一个重点课题。

进程和线程的区别

进程是一个独立的运行环境,而线程是在进程中执行的一个任务。他们两个本质的区别是是否单独占有内存地址空间及其它系统资源(比如I/O)

  • 进程单独占有一定的内存地址空间,所以进程间存在内存隔离,数据是分开的,数据共享复杂但是同步简单,各个进程之间互不干扰;而线程共享所属进程占有的内存地址空间和资源,数据共享简单,但是同步复杂。
  • 进程单独占有一定的内存地址空间,一个进程出现问题不会影响其他进程,不影响主程序的稳定性,可靠性高;一个线程崩溃可能影响整个程序的稳定性,可靠性较低。
  • 进程单独占有一定的内存地址空间,进程的创建和销毁不仅需要保存寄存器和栈信息,还需要资源的分配回收以及页调度,开销较大;线程只需要保存寄存器和栈信息,开销较小。

另外一个重要区别是,进程是操作系统进行资源分配的基本单位,而线程是操作系统进行调度的基本单位,即CPU分配时间的单位 。

多进程方式确实可以实现并发,但使用多线程,有以下几个好处:

  • 进程间的通信比较复杂,而线程间的通信比较简单,通常情况下,我们需要使用共享资源,这些资源在线程间的通信比较容易。
  • 进程是重量级的,而线程是轻量级的,故多线程方式的系统开销更小。

协程

子程序,或者称为函数,在所有语言中都是层级调用。子程序调用是通过栈实现的,一个线程同一时间就是执行一个子程序。 协程本质上也是子程序,协程作为子程序最大的特征是可中断可恢复。

协程是⼀种在程序中处理并发任务的⽅案,也是这种⽅案的⼀个组件。它和线程属于⼀个层级的概念,是⼀种和线程不同的并发任务解决⽅案:⼀套系统(可以是操作系统,也可以是⼀种编程语⾔)可以选择不同的⽅案来处理并发任务,你可以使⽤线程,也可以使⽤协程。

最重要的是,协程不是被操作系统内核所管理,而完全是由程序所控制(也就是在用户态执行)。这样带来的好处就是性能得到了很大的提升,不会像线程切换那样消耗资源。

常规子程序

子程序执行完返回把控制权返还给调用这个子程序的上层,让上层继续往下执行,一层套一层,这就是层级调用。

特征:

  • 执行完毕才返回
  • 不可中断

协程

协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。

特征:

  • 可以执行到一半先返回
  • 可中断、挂起
  • 再次执行可恢复状态

多线程相比, 协程的优点在于

  • 避免了线程创建/切换带来的消耗
  • 不需要多线程的锁机制

参考文献

进程与线程基本概念

Java并发编程:进程和线程之由来

程序员小灰—什么是协程