老生常谈之进程与线程
进程
- 程序执行时的一个实例
- 每个进程都有独立的内存地址空间
- 是操作系统进行资源分配和调度的基本单位
- 进程里的堆,是一个进程中最大的一块内存,被进程中的所有线程共享,进程创建时分配,主要存放new创建的对象实例
- 进程的方法区,是用来存放进程中的代码片段的,是线程共享的
- 在多线程OS中,进程不是一个可执行的实体,即一个进程至少创建一个线程去执行代码
线程
- 进程中的一个实体
- 进程的一个执行路径
- CPU调度和分派的基本单位
- 现成本身是不会独立存在的
- 当前线程CPU时间片用完后,会让出CPU等下次轮到自己再执行
- 操作系统不会单独为线程分配内存,线程组之间只能共享所属进程的资源
- 现成只拥有在运行中必不可少的资源(比如程序计数器、栈)
- 线程的程序计数器就是为了记录该线程在让出CPU时候的执行地址,待再次时间片分配到自己时继续执行
- 每个线程有自己的栈资源,用于存储该线程的局部变量和调用栈帧,其他线程无权访问
关系
- 一个程序至少一个进程,一个进程至少有一个线程;进程中的多个线程是互相共享资源的
- Java中启动main函数的时候就启动了一个JVM的进程,main函数所在的线程就是主线程。
- 多个线程共享进程的堆空间和方法区资源,每个线程有自己的程序计数器和栈资源。
区别
- 本质:进程是操作系统进行资源调度和分配的基本单位;线程是任务调度和执行的基本单位
- 内存分配:系统在运行的时候会为每个进程分配不同的内存空间,建立数据表来维护代码段、堆栈段和数据段;除了 CPU 外,系统不会为线程分配内存,线程所使用的资源来自其所属进程的资源
- 资源拥有:进程之间的资源是独立的,无法共享;同一进程的所有线程共享本进程的资源,如内存,CPU,IO 等
- 开销:每个进程都有独立的代码和数据空间,程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行程序计数器和栈,线程之间切换的开销小
- 通信:进程间通信 以IPC(管道,信号量,共享内存,消息队列,文件,套接字等)方式通信 ;同一个进程下,线程间可以共享全局变量、静态变量等数据进行通信,做到同步和互斥,以保证数据的一致性
- 调度和切换:线程上下文切换比进程上下文切换更快,代价更小
- 执行过程:每个进程都有一个程序执行的入口,顺序执行序列;线程不能够独立执行,必须依存在应用程序中,由程序的多线程控制机制控制
- 健壮性:每个进程之间的资源是独立的,当一个进程崩溃时,不会影响其他进程;同一进程的线程共享此线程的资源,当一个线程发生崩溃时,此进程也会发生崩溃,稳定性差,容易出现共享与资源竞争产生的各种问题,如死锁等
为什么要有线程
每个进程都有自己的地址空间,即进程空间。操作系统为了避免为每个请求都创建进程,引入线程