并行:同一时刻
并发:同一时间段
硬件基础
CPU核心数和线程数:以AMD5600为例(6核心12线程 这里是指并行),这6个核心中的每一个都能够独立完成CPU的工作,也就是生产效率比单核提升了5倍。
超线程:核心数 < 线程数, 传统的线程和核心都是1对1的,超线程主要就是吧CPU的功能再分解,比如CPU里面有浮点运算和整数运算,我这两个模块是不是可以并行工作。超线程的提升跟实际调度的线程息息相关,因为在一个CPU核心中,这两个线程还是存在竞争关系的,只是当他们不竞争的时候才能榨干CPU的性能。
其实关于硬件的核心、线程我们理解到这里就足够了,因为操作系统帮我们做了封装,我们真正在程序中调用线程时,操作系统会找到空闲的核心帮我们运行程序。
进程和线程(软件程序、应用)
进程是操作系统分配调度资源的基本单位。
线程是操作系统分配调度CPU资源的基本单位。
一般来讲一个软件可能对应一个或多个程序,每个程序对应一个进程,而一个进程可以对应多个线程且至少有一个主线程
软件->程序=进程->线程
为什么引入了线程
线程的产生就是为了进一步解放CPU的生产能力
比如程序运行要一直循环ABC三步工序,
A0->B0->C0->A1->B1->C1->...,假设A是运行准备工作,B是CPU工作,C是绘制或者IO操作。且C不会影响下一次A、B的工作(这里是要能够分割的,比较关键的条件)那么我是不是B0做完之后不用等C0做完就直接把B1算出来,那么我节约的时间是不是C0 + A1 + B1 - MAX(CO, A1 + B1)。把一个程序中CPU相关的任务拆分出来和程序中的非CPU相关的任务并行处理。如果新线程的任务和主线程的任务需要同步的话就需要加信号量来同步,即使同步,也比按A0->B0->C0->A1->B1->C1顺序运行来的效率要高。
线程引入除了提高效率之外还有一个优点就是避免阻塞,比如说我有一个很大的资源要加载,把逻辑写在主线程会导致渲染、响应等逻辑卡顿 (假设都在主线程里面)。
windows平台线程调度的实验:
当我们vs控制台进程的时候,我们写一个while死循环,发现进程CPU的占用率是1/核心数。
当我们再加入一个死循环,发现进程CPU的占用率是2/核心数。
原因分析:
当只有一个主线程时,同一时刻最多只有一个核心能分配到该线程的任务。
当有一个主线程一个子线程时,同一时刻,有两个核心一个可以调用主线程一个可以调用子线程。
反思
由于调度是以线程为单位,且现在的CPU大多都是多核,为了压榨CPU的性能。我们在开发中还是要拆分任务,更大程度的发挥CPU的多核能力。