多线程系列(1)
引言
这是Java多线程系列的第一篇,接下来会在每天都更新多线程的东西,从底层带你一步一步的了解多线程。切记一定要从头开始看。
目录
)
多核CPU和多CPU的关系?
计算机的组成
我们知道现在的计算机都遵循冯诺依曼模型:每个计算机主要包括5大基本组成部分,运算器,控制器,存储器,输入和输出。如下图示:
实线代表数据的流向,虚线代表控制流。根据上面的冯诺依曼计算机模型,现代计算机的组成如下所示:
其中CU指的是控制器,ALU指的是计算机器。
然后我们讨论一下CPU的运行原理,如下图所示:
第一步:控制单元根据指令计数器(指令计数器(PC):存放当前欲执行指令的地址,具有计数功能(PC)+ 1
)的值去主内存中找到下一步要执行的指令。
第二步:指令计数器找到要执行的指令后,指令寄存器把要执行的指令放到指令寄存器(存放当前欲执行的指令)里面。
第三步:控制单元根据指令寄存器里面的指令去控制存储单元(一般指的是缓存)和运算单元,其中存储单元根据指令需要的数据首先去缓存中查找,如果缓存中不存在要是使用的数据,那么就去主内存中查找,然后加载到缓存中,然后再加载到寄存器,然后计算单元去寄存器中去查找需要的数据去执行运算。
第四步:把计算结果保存到存储单元,然后等待一段合适的时间刷到主内存中。
第五步:执行下一条指令,周而不复始循环上述步骤。
提示:寄存器分为:通用寄存器和专用寄存器,专用寄存器主要是用来寄存指令的,通用寄存器可用于传送和暂存数据,也可参与算术逻辑运算,并保存运算结果。
多核CPU与多CPU
多个物理CPU通过总线进行通信,效率较低,如下图所示:
多核CPU,不同的核通过L2或L3通信(一般一级缓存与二级缓存是每个核心独有的,三级缓存才是多个核心一起共享的,但是如果CPU中没有三级缓的共享2缓,有三缓的共享三缓 ),下面的图是没有三级缓存的,共享L2缓存。
CPU的缓存:CPU缓存是位于CPU与内存之间的临时数据交换器,它的容量比内存小的多但是交换速度却比内存要快得多。CPU缓存一般直接跟CPU芯片集成或位于主板总线互连的独立芯片上。
随着多核CPU的发展,CPU缓存通常分成了三个级别:L1
,L2
,L3
。级别越小越接近CPU,所以速度也更快,同时也代表着容量越小。L1 是最接近CPU的, 它容量最小(例如:32K
),速度最快,每个核上都有一个 L1 缓存,L1 缓存每个核上其实有两个 L1 缓存, 一个用于存数据的 L1d Cache(Data Cache),一个用于存指令的 L1i Cache(Instruction Cache)。L2 缓存 更大一些(例如:256K
),速度要慢一些, 一般情况下每个核上都有一个独立的L2 缓存; L3 缓存是三级缓存中最大的一级(例如3MB),同时也是最慢的一级, 在同一个CPU插槽之间的核共享一个 L3 缓存。
如果core1中的Thread1要读取数据了,首先会去自己的所在的core1的L1缓存中去找,如果L1缓存中不存在的话,就去L3缓存中找,如果L3缓存中也不存在的话就去主内存中去找,然后一步一步加载到L1缓存中,然后core1的的Thread1再使用此数据。
进程和线程
在这里首先简单提一下Java多线程,接下来会有具体小结去介绍
进程说白了就是我们电脑中运行的一个应用,比如爱奇艺或者qq都是一个独立的进程,一个进程包含多个线程,比如爱奇艺中播放一个视频就是一个单独的线程,多个线程共享进程的资源,可以说线程是轻量级的进程。
- 联系
程是进程的一部分,一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
- 区别:理解它们的差别,从资源使用的角度出发。(所谓的资源就是计算机里的中央处理器,内存,文件,网络等等)
根本区别:进程是操作系统资源分配的基本单位,而线程是CPU任务调度和执行的基本单位.
在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。
进程和线程在多核cpu,多cpu中的运行关系
操作系统会拆分CPU为一段段时间的运行片,轮流分配给不同的程序。对于多cpu,多个进程可以并行在多个cpu中计算,当然也会存在进程切换;对于单cpu,多个进程在这个单cpu中是并发运行,根据时间片读取上下文+执行程序+保存上下文。同一个进程同一时间段只能在一个cpu中运行,如果进程数小于cpu数,那么未使用的cpu将会空闲。
参考:https://www.cnblogs.com/valjeanshaw/p/11469514.html
协程
协程(Coroutines)是一种比线程更加轻量级的存在,正如一个进程可以拥有多个线程一样,一个线程可以拥有多个协程。
协程不是被操作系统内核所管理的,而是完全由程序所控制,也就是在用户态执行。这样带来的好处是性能大幅度的提升,因为不会像线程切换那样消耗资源。
协程不是进程也不是线程,而是一个特殊的函数,这个函数可以在某个地方挂起,并且可以重新在挂起处外继续运行。所以说,协程与进程、线程相比并不是一个维度的概念。
一个进程可以包含多个线程,一个线程也可以包含多个协程。简单来说,一个线程内可以由多个这样的特殊函数在运行,但是有一点必须明确的是,一个线程的多个协程的运行是串行的。如果是多核CPU,多个进程或一个进程内的多个线程是可以并行运行的,但是一个线程内协程却绝对是串行的,无论CPU有多少个核。毕竟协程虽然是一个特殊的函数,但仍然是一个函数。一个线程内可以运行多个函数,但这些函数都是串行运行的。当一个协程运行时,其它协程必须挂起。
协程的暂停完全由程序控制,线程的阻塞状态是由操作系统内核来进行切换。因此,协程的开销远远小于线程的开销。