1. CPU与内核
CPU中文全称中央处理器,拥有一个或多个运算内核,所有的计算、接受/存储命令、处理数据等都由CPU的内核处理。
简单来说,一个CPU具有一或多个内核,而指令的执行是由其中的某个内核处理的。
2. 并发与并行
- 并发:两个及两个以上的作业在同一 时间段 内执行(期间某一时刻并不是同时在执行的);
- 并行:两个及两个以上的作业在同一 时刻 内执行。
- [并发] 家庭主妇做饭、打扫卫生、给孩子喂奶,她一个人轮流 交替 做这三件事情,这就是并发;
- [并发 + 并行] 家庭主妇雇佣了一个保姆,保姆与主妇 一起 且 交替 做这三件事情(会产生竞争,例如锅只有一口,一个人用锅的时候,另一个人就只能等待);
- [并行] 家庭主妇雇佣了两个保姆,主妇负责喂奶,保姆1负责做饭,保姆2负责打扫卫生,三人 一起 工作且 互不干扰。
首先先讲讲时间片的概念:
时间片简单地理解为是一段 操作系统分配给某个线程的占用某个内核的时间。若「线程A」抢到了「内核①」的「时间片1」,意味着在这段时间内,「线程A」将独享「内核①」。
2.1. 并发(Concurrent)
从宏观的角度看是并行的(因为时间片很短,大约是15ms,人能感知的时间段大约为100ms,而100ms内CPU进行了若干次上下文切换,人很难感知这样的差距);
从微观的角度看是串行的(因为实际上是在交替执行串行计算,而并非是真正意义上的同时运算)
当 内核数 < 线程数 时,就会有并发的情况。
在 同个时间段内 将这些线程的任务都完成,内核根据各线程抢占的时间片,交替执行 不同线程中的指令流。换言之,其中的某一时刻必定存在 不执行的线程。
下图以 单核双线程 为例进行说明:
2.2. 并行
当 内核数 > 线程数时,就会有并行的情况。
并行就是真正意义上的 同时执行,在其中的任一一个时刻,这些线程都是同时被执行的。
3. 线程间的上下文切换
上图中有一个「上下文切换」的过程,这里做个简单介绍:
- [什么是上下文] 线程执行时的运行条件与状态,比如当前的程序计数器信息、局部变量表信息以及线程栈信息等。
- [什么时候发生上下文切换] 当出现以下任意一个情况,线程就会从占有CPU状态中退出,即发生上下文切换:
- 主动让出CPU,比如调用了
sleep()
或wait()
等; - 当前时间片消耗完毕(上文中提到的就是这种情况);
- 调用了阻塞类型的系统中断,比如请求IO,线程被阻塞;
- 被终止或结束运行。
- 主动让出CPU,比如调用了
据此,可以总结:线程的上下文切换是指CPU内核的上下文(某个线程在某一时刻的运行条件与状态)发生了变换。
4. 效率提升
- 单核CPU下,多线程并不能提高效率(反而还因为频繁的上下文切换而影响了效率),但是能让CPU在不同的线程进行切换,不至于让某个线程始终独占CPU而导致其他线程无法执行;
- 多核CPU下并行跑多个线程,通常情况下都能显著提升效率。