1.1、什么是进程

假如有两个程序 A 和 B,程序 A 执行到一半的过程中,需要读取大量的数据输入(I/O

操作),而此时 CPU 只能静静地等待读取读取完数据才能继续执行,这样就白白浪费了 CPU

资源。是不是在程序 A 读取的过程中,让程序 B 去执行,当程序 A 读取完数据之后,让程

序 B 暂停,然后让程序 A 继续执行?

当然没问题,但这里有一个关键词:切换(I/O 切换或时间轮询切换)。

既然是切换,那么就涉及到了状态的保存,状态的恢复,加上程序 A 与程序 B 所需要

的系统资源(内存、硬盘、键盘等等)是不一样的,自然而然的就需要有一个东西去记得程序

A 和程序 B 分别需要什么资源,怎么去识别两个程序,所以就有了一个叫进程的抽象。

即使可以利用的 cpu 只有一个(早期的计算机确实如此),也能保证支持(伪)并发

的能力。将一个单独的 cpu 变成多个虚拟的 cpu(多道技术:时间多路复用和空间多路复

用+硬件上支持隔离),没有进程的抽象,现代计算机将不复存在。

举个栗子(单核+多道,实现多个进程的并发执行):

张三在一个时间段内有很多任务要做:写代码,看书,交女朋友,王者荣耀上分…

但同一时刻只能做一个任务(cpu 同一时间只能干一个活),如何才能玩出多个任务并

发执行的效果?

写一会代码,再去跟某一个女孩聊聊天,再去打一会王者荣耀,英雄死了再看看书…

这就保证了每个任务都在进行中。

1.2、进程与程序的区别

程序仅仅只是一堆代码而已,而进程指的是程序的运行过程。(抽象的概念)

tips:程序是程序,进程是进程,程序不运行,永远不是进程。

进程定义:

进程即程序(软件)在一个数据集上的一次动态执行过程。进程是对正在运行程序的一个

抽象。进程一般由程序、数据集、进程控制块三部分组成。一个进程是一份独立的内存空间。

多个进程之间用户程序无法互相操作。

程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成;

数据集:是程序在执行过程中所需要使用的资源;

进程控制块:用来记录进程的外部特征,描述进程的执行变化过程,系统可以利用它来

控制和管理进程,它是系统感知进程存在的唯一标志。

举个栗子:

想象一位厨师正在为他的女儿烘制生日蛋糕

他有做生日蛋糕的食谱,厨房里有所需的原料:面粉、鸡蛋、韭菜,蒜泥等

在这个比喻中:

做蛋糕的食谱就是程序(即用适当形式描述的算法)

厨师就是处理器(cpu)

而做蛋糕的各种原料就是输入数据

进程就是厨师阅读食谱、取来各种原料以及烘制蛋糕等一系列动作的总和

现在假设厨师的儿子哭着跑了进来,说:头被蜜蜂蛰了。

厨师想了想,处理儿子蛰伤的任务比给女儿做蛋糕的任务更重要,于是厨师就记录下他

照着食谱做到哪儿了(保存进程的当前状态),然后拿出一本急救手册,按照其中的指示处理

蛰伤。这里,我们看到处理器(cpu)从一个进程(做蛋糕)切换到另一个高优先级的进程(实施

医疗救治),每个进程拥有各自的程序(食谱和急救手册)。当蜜蜂蛰伤处理完之后,这位厨师

又回来做蛋糕,从他离开时的那一步继续做下去。

需要强调的是:同一个程序执行两次,那也是两个进程,比如打开 PotPlayer,虽然都

是同一个软件,但是一个可以播放 Java,一个可以播放 Python。

1.3、什么是线程

进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程

才是 CPU 上的执行单位。在操作系统中,每个进程有一个地址空间,而且默认就有一个控

制线程(主线程)。多线程(即多个控制线程)的概念是,在一个进程中存在多个控制线程,

多个控制线程共享该进程的地址空间。线程不能够独立执行,必须依存在进程中。一个线程

可以创建和撤销另一个线程(子线程),同一个进程中的多个线程之间可以并发执行。

举个栗子:一条流水线工作的过程

一条流水线(线程)必须属于一个车间,一个车间的工作过程是一个进程,车间负责把

资源整合到一起,是一个资源单位,而一个车间内至少有一个流水线,流水线的工作需要电

源,电源就相当于 CPU,多线程相当于一个车间内有多条流水线,都共用一个车间的资源。

再比如:

开启一个文本处理软件进程,该进程肯定需要办不止一件事情,比如监听键盘输入,处

理文字显示,定时自动将文字保存到硬盘,这三个任务操作的都是同一块数据,因而不能用

多进程。只能在一个进程里并发地开启三个线程,如果是单线程,那就只能是,键盘输入时,

不能处理文字和自动保存,自动保存时又不能输入和处理文字。

1.4、并发和并行

无论是并行还是并发,在用户看来都是’同时’运行的,不管是进程还是线程,都只是一

个任务而已,真是干活的是 cpu,cpu 来做这些任务,而一个 cpu 同一时刻只能执行一个

任务

4.1、并发(串行)

是伪并行,即看起来是同时运行。单个 cpu+多道技术就可以实现并发。

渣男例:

你是一个 cpu,你同时谈了三个女朋友,每一个都可以是一个恋爱任务,你被这三个任

务共享,要玩出并发恋爱的效果,应该是你先跟女友 1 去看电影,看了一会说:不好,我

要拉肚子,然后跑去跟第二个女友吃饭,吃了一会说:那啥,我去趟洗手间,然后跑去跟女

友 3 喝下午茶.

4.2、并行

同时运行,只有具备多个 cpu 才能实现并行

单核下,可以利用多道技术,多个核,每个核也都可以利用多道技术(多道技术是针对

单核而言的)

有四个核,六个任务,这样同一时间有四个任务被执行,假设分别被分配给了 cpu1,

cpu2,cpu3,cpu4,可能任务 1 遇到 I/O 就被迫中断执行,此时任务 5 就拿到 cpu1 的时间片去执行,这就是单核下的多道技术,而一旦任务 1 的 I/O 结束了,操作系统会重新

调用它(进程的调度、分配给哪个 cpu 运行,由操作系统说了算),可能被分配给四个 cpu

中的任意一个去执行。

4.3、总结

并发:系统具有处理多个任务的能力

并行:系统具有同时处理多个任务的能力

思考:并发是不是并行的一个子集?并行是不是并发的一个子集?

答案:parallelism must be concurrency, and concurrency is not necessarily parallel

并发编程基本概念_消息队列

并发编程基本概念_单核_02

1.5、同步和异步

并发编程基本概念_单核_03

5.1、同步

同步的思想是:所有的操作都做完,才返回给用户。这样用户在线等待的时间太长,给

用户一种卡死了的感觉(就是系统迁移中,点击了迁移,界面就不动了,但是程序还在执行,

卡死了的感觉)。这种情况下,用户不能关闭界面,如果关闭了,即迁移程序就中断了。

5.2、异步

将用户请求放入消息队列,并反馈给用户友好提示,系统迁移程序启动,你可以关闭浏

览器了。然后程序再慢慢地去写入数据库去。这就是异步。用户没有卡死的感觉,会告诉你,

你的请求系统已经响应了。你可以关闭界面了。

5.3、总结

同步,是所有的操作都做完,才返回给用户结果。即写完数据库之后,在响应用户,用

户体验不好。

并发编程基本概念_单核_04

异步,不用等所有操作等做完,就响应用户请求。即先响应用户请求,然后慢慢去写数

据库,用户体验较好。

并发编程基本概念_数据_05

异步操作例子:

为了避免短时间大量的数据库操作,可以使用缓冲机制,也就是消息队列。先将数据放

入消息队列,然后再慢慢写入数据库。

引入消息队列机制,虽然可以保证用户请求的快速响应,但是并没有使得我数据迁移的

时间变短(即 80 万条数据写入 mysql 需要 1 个小时,用了缓冲机制之后,还是需要 1 个

小时,只是保证用户的请求的快速响应。用户输入完 http url 请求之后,就可以把浏览器

关闭了,干别的去了。如果不用缓冲机制,浏览器不能关闭)。

同步就没有任何价值了吗?

有。比如银行的转账功能。打电话等