CPU 线程 与 进程的关系

3,605 阅读6分钟

物理核

经常听到CPU是几核几核的,比如4核CPU,8核CPU,比如服务器很多都是8核CPU
一台PC或者服务器,可以配置多个CPU,CPU安装在主板上。 以Linux服务器为例

cat /proc/cpuinfo

得到

processor   : 0
vendor_id   : GenuineIntel
cpu family  : 6
model       : 60
model name  : Intel(R) Core(TM) i7-4700MQ CPU @ 2.40GHz
stepping    : 3
microcode   : 0x22
cpu MHz     : 2393.631
cache size  : 6144 KB
physical id : 0
siblings    : 8
core id     : 0
cpu cores   : 4
...

其中有几个physical id,机器上就安装了几个物理CPU
cpu core记录了每个物理CPU,内部有几个物理核
siblings 代表每个物理CPU有多少个逻辑核

逻辑核

经常听人说什么4核4线程,4核8线程
本来一个核会对应处理一个线程(即逻辑处理单元),但为了提高效率,后来Intel的超线程技术(HT)将物理核虚拟成逻辑处理单元,将一个物理核变为2个虚拟核,即每个核两个线程。

进程与线程

两种常见解释

  1. 进程和线程都是一个时间段的描述,是CPU工作时间段的描述。
  2. 进程是资源分配的最小单位,线程是CPU调度的最小单位

解释:

  1. CPU太快了,只有缓存存储器SRAM才能勉强追上它的速度,因此,一台机器上同时开30个程序,CPU可以把这30个程序变成顺序执行,每个只执行一小段,立马切换到下一个程序,再执行一小段,再切回来,人是无感知的。
  2. 一个程序准备开始执行的时候,相关资源必须要准备好,比如RAM地址,显卡,磁盘资源,这些准备好的东西打包一起就叫做上下文环境,然后CPU开始执行程序A,当然只执行了一小段时间,CPU就要切换到别的程序执行B,以保证几个程序的并发,切换之前要把A的上下问状态保存起来,下次切回来的时候接着用。
  3. 因此,进程就是包换上下文切换的程序执行时间总和 = CPU加载上下文+CPU执行+CPU保存上下文
  4. 进程的颗粒度太大,每次都要有上下的调入,保存,调出。线程就是进程的小分支,比如进程A有a,b,c三个线程,那么线程a,b,c就共享了进程A的上下文环境,成为了更细小的执行时间。

程序中的线程 与 CPU的线程

看到这里会懵逼,假设一台8CPU32核的服务器,是不是跑的程序最多只能开32个线程呢?
答案当然是否定的,我们常说的进程中的线程,与CPU的线程,虽然都叫线程,但完全不是一回事。
程序的线程是软件概念,一个程序可以有多个线程,可以在一个CPU核上轮流并发执行。
CPU的线程是硬件的概念,就是核。八线程就是能让八个线程并行执行。

linux中的线程

有人说linux中不存在线程的概念,查了一下,大概是说:

WINDOWS中是真的有进程和线程的,进程来准备上下文环境,是一个实例,线程是CPU调度的最小单位,程序代码执行的最小单元。  
linux中一个进程的多个线程在内核中只是多个特殊的进程,它们虽然有各自的进程描述结构,却共享同一个代码上下文。在Linux上,这样的进程称为轻量级进程(Light weight process)。  每个用户线程对应一个LWP,LWP又对应一个内核线程。  
LinuxThreads是用户空间的线程库,所采用的是线程-进程1对1模型(即一个用户线程对应一个轻量级进程,而一个轻量级进程对应一个特定的内核线程),将线程的调度等同于进程的调度,调度交由内核完成,而线程的创建、同步、销毁由核外线程库完成。

内核线程与用户线程

内核线程就是内核的分身,一个分身可以处理一件特定事情。我们的程序是很少有直接调取内核线程的,而是操作用户线程,用户线程与内核线程有一对一,多对一,多对多。

多对多模型

映射多个用户级线程到一个内核线程。
如果一个线程执行阻塞系统调用,那么整个进程将会阻塞。再者,因为任一时间只有一个线程可以访问内核,所以多个线程不能并行运行在多处理核系统上。 早期JAVA用,目前几乎没人用了。

一对一模型

该模型在一个线程执行阻塞系统调用时,能够允许另一个线程继续执行,所以它提供了比多对一模型更好的并发功能;它也允许多个线程并行运行在多处理器系统上。

这种模型的唯一缺点是,创建一个用户线程就要创建一个相应的内核线程。由于创建内核线程的开销会影响应用程序的性能,所以这种模型的大多数实现限制了系统支持的线程数量。Linux,还有 Windows 操作系统的家族,都实现了一对一模型。

多对多模型

多路复用多个用户级线程到同样数量或更少数量的内核线程。内核线程的数量可能与特定应用程序或特定机器有关(应用程序在多处理器上比在单处理器上可能分配到更多数量的线程)。
虽然多对一模型允许开发人员创建任意多的用户线程,但是由于内核只能一次调度一个线程,所以并未增加并发性。虽然一对一模型提供了更大的并发性,但是开发人员应小心,不要在应用程序内创建太多线程(有时系统可能会限制创建线程的数量)。
多对多模型没有这两个缺点:开发人员可以创建任意多的用户线程,并且相应内核线程能在多处理器系统上并发执行。而且,当一个线程执行阻塞系统调用时,内核可以调度另一个线程来执行。