- 进程
如果从计算机发展的时间线来讲,
在早期的计算机中不含操作系统,他们从头到尾只执行一个程序,并且这个程序能访问计算机中所有的资源。
操作系统的出现使得计算机每次能运行多个程序,并且不同的程序都能够在自己单独的进程中运行,操作系统为各个独立的进程分配各种资源。
那么从程序层面来讲:
进程是代码在数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。
- 线程
在早期的分时系统中,每个进程相当于一台虚拟的冯·诺依曼计算机,它拥有存储指令和数据的内存空间,根据机器语言的语义以串行的方式执行指令。那么多线程就是将这种串行执行的方式给它分解开来,多个线程去共享这一个进程范围内的资源,同时进行调度工作,去完成这个进程想要达到的目标。
线程是进程中的一个实体,线程本身是不会独立存在的,它是进程的一个执行路径,一个进程中至少有这样一个执行路径,也可以有多个,就是进程中可以包含至少一个也可以是多个的线程,多个线程共享进程的资源,分解进程的任务。
- 联系
操作系统在资源分配的时候是把资源分配给进程的,但是 CPU 资源它在分配的时候,是分配给每个线程的,因为真正要占用 CPU 运行的是线程,也就是说线程是 CPU 分配的基本单位。
在 Java 程序里,当我们启动 main 函数时其实就是启动了一个 JVM 的进程,而 main 函数所在的线程时这个进程中的一个线程,也称主线程。
进程和线程的关系如图所示:
由图可以看到,一个进程中有多个线程,多个线程共享进程中的堆和方法区资源,但是每个线程有自己的程序计数器和栈区域。
- 再理解一点线程
线程中的程序计数器是一块内存区域,用来记录线程当前要执行的指令地址。那么为何要将程序计数器设计为线程私有呢? 因为线程是占用 CPU 的执行单位,而 CPU 一般是使用时间片轮转方式让线程轮询占用的,所以当前线程 CPU 时间片用完后,要让出 CPU, 等下次轮到自己的时候再执行。 那么这个程序计数器其实就是记录了该线程让出 CPU 时的执行地址的, 待再次分配到时间片时线程就可以从自己私有的计数器制定地址继续执行了。
另外每个线程都有自己的栈资源,用于存储该线程的局部变量,这些局部变量是该线程私有的, 其他线程是访问不了的,除此之外还可以用来存放线程的调用栈帧。
堆是一个进程中最大的一块内存,堆是被进程中的所有线程共享的,是进程创建时分配的,堆里面主要存放使用 new 操作创建对象的实例。
方法区则用来存放 JVM 加载的类、常量及静态变量等信息,也是线程共享的。