操作系统: 进程与线程
进程 = 资源管理 + 线程
进程是资源分配单位
线程是 CPU 调度单位
到底什么是进程?怎么理解进程?
一般,可以把运行的程序,看成进程。
程序在整个执行过程中的描述,是进程。
程序在运行过程中,会消耗各种资源,会占用 CPU、内存和网络,会使用文件系统 I/O
进程就是运行的程序的执行过程
为什么要有进程?
最初的操作系统,只能支持跑一个程序。
随着计算机的发展,CPU 的能力越来越强,内存越来越多。可以在内存中,放入更多的可以运行的程序。
操作系统中,各个运行的程序的状态。用程序来表示,不够准确,需要新的概念。
因为可能存在内存中,一个程序跑了多份的情况。
内存中,一个程序的多个实例,怎么来清楚的表示出来呢?
进程的概念,就出来了。进程用来表示程序整个的执行过程
我们写的程序,编译为可执行程序,放在文件系统里面,格式是可执行文件,他是静态的。
只有当我们的操作系统,把可执行程序,调入我们的内存中之后,让这个程序能够执行起来。
执行,也就是这个程序能够通过 CPU , 来执行程序中的一条条指令,然后对相应的数据,进行处理,完成一定的功能。
这个过程,是一个动态执行的过程,我们称为进程。
进程的标准答案:一个具有一定独立功能的程序,在一个数据集合上的,一次动态执行过程
这整个的过程,就是进程
为什么要有线程?
多进程,消耗太大。
进程之间,他们的地址空间是独立的,一般通过沙盒保护。
进程间通信,交换数据,需要通过操作系统,开销大,过程相对复杂。
多线程,开销就小了一些。
多线程除了实现了并发,还共享相同的地址空间,也就是共享相同的资源。
一个线程产生的数据,另一个线程可以很容易地拿到。
线程间通信,比较简单。
什么是线程?
线程是进程中的一条执行流程
从资源组合的角度看:
进程,就是用来管理资源的。资源包括地址空间(代码段、数据段)、打开的文件、访问的网络。
把进程执行的功能、执行的状态,做一些拆分,交给线程来管理。
从运行的角度看:
线程就是,代码在这个资源平台上的一条执行流程。
进程 = 资源管理 + 线程
进程除了管理资源,还有一系列的线程,用来完成执行的过程。
一个进程的多个线程,共享进程所拥有的所有资源。
线程 = 进程 - 资源管理
线程,用来完成控制流的管理
区别:
-
进程是资源分配单位,线程是 CPU 调度单位
-
进程拥有一个完整的资源平台,
-
线程只独享必不可少的资源,如寄存器和栈,用于维持自己的、每个线程独立的控制流。进程的资源,进程的多个线程共享
-
线程能减少并发执行的时间和空间开销
例如: 线程的创建时间比进程短
因为进程在创建过程中,需要创建其他的管理信息。如: 内存要怎么管理,打开的文件要怎么管理
创建线程,直接重用该线程所属的进程资源,这些资源已经管理好了。所以线程不需要创建这些管理信息
操作系统: 计算机的堆和栈
对象堆
堆是用来容纳应用程序,动态分配的内存区域。
当程序使用 malloc 或 new 分配内存的时候,得到的内存来自堆里。
没有堆,全局变量就不能动态的产生,只能在编译的时候定义,这是不够用的。
堆空间,进程的地址空间中,除了可执行文件、共享库和栈之外,剩余的未分配的空间都可以用作堆空间
堆空间一般比栈空间大很多,可以有几十到几百 MB 的容量。
函数栈
栈是用于维护函数调用的上下文。
栈保存了一个函数调用所需要的维护信息。
离开了栈,函数调用就没法实现。
没有栈,就没有函数,没有局部变量。
栈上的数据在函数返回的时候,就会被释放掉,所以无法将数据传递至函数外部。
堆与栈的其他区别, Java 版本:
- 从存储角度来看,堆和栈存储的内容不一样
堆空间,里面放实例对象
栈空间,里面放基本数据类型变量,和对象的引用
- 从存取速度来看,
栈空间,存取速度快,栈里面是基本数据类型,与对象的引用指针。程序编译期间,就能决定栈空间的存储。
堆空间,存取速度慢。程序运行后,对象才能动态分配内存,创建实例。堆空间 > 栈空间
- 从线程访问来看,
每个线程都有自己的一个栈,
所有线程共享一个堆
- 从 GC 垃圾回收的角度:
栈空间,回收比较频繁,栈区变量的生命周期是,从方法进入到方法结束。
堆空间,回收频次相对低。分为新生代、老年代,满足条件,才能激发 GC