操作系统是一组计算机资源管理的软件的统称。目前常见的操作系统有Linux系列、Window系列、IOS系列、Android系列、鸿蒙系列、Unix系列、OSX系列等操作系统
操作系统有两个基本功能:
(1)防止硬件被时空的应用滥用
(2)向应用程序提供简单一致的机制来控制复杂庞大而又通常大相径庭的低级软件设备
,每个应用程序运行于现代操作系统之上时,操作系统会提供一种抽象,好像系统上只有这个程序在运行,所有的硬件资源都被这个程序使用,这种假象是通过了一个进程的概念来完成的,进程可以称得上是计算机科学中最成功和最重要的概念之一。
进程是操作系统对一个正在运行的程序的一种抽象理解,换句话说,就是可以把程序的一次运行过程看作是进程,同时,在操作系统内部,进程又是操作系统进行分配资源的基本单位。
计算机内部要管理任何现实事务,都需要抽象成为一组有关联的、互为一体的数据。在java语言中,我们可以通过类/对象来描述这一特征。
// 以下代码是 Java 代码的伪码形式,重在说明,无法直接运行
class PCB {
// 进程的唯一标识 —— pid;
// 进程关联的程序信息,例如哪个程序,加载到内存中的区域等
// 分配给该资源使用的各个资源
}
这样,每一个PCB对象,就代表着一个个实实在在运行的程序,也就是我们所说的进程。
操作系统通过这种数据结构,例如线性表、搜索树将PCB对象组织起来,方便管理时进行增删改查操作。
为了便于讨论和理解,我们大部分的场景下假设是单CPU单核的计算机。
操作系统对CPU资源的分配,采用的是时间模式 —— 不同的进程在不同的时间段去使用 CPU 资源
操作系统对内存资源的分配,采用的是空间模式 —— 不同进程使用内存中的不同区域,互相之间不会干扰。
如上所述,进程是操作系统进行资源分配的最小单位,这意味着各个进程互相之间是无法感受到对方存在的,这就是操作系统抽象出进程这一概念的初衷,这样便带来了进程之间互相具备”隔离性(Isolation)“。
但现代的应用,要完成一个复杂的业务需求,往往无法通过一个进程独立完成,总是需要进程和进程进行配合地达到应用的目的,如此,进程之间就需要有进行“信息交换“的需求。进程间通信的需求就应运而生。
目前,主流操作系统提供的进程通信机制有如下:
1. 管道
2. 共享内存
3. 文件
4. 网络
5. 信号量
6. 信号
其中,网络是一种相对特殊的 IPC 机制,它除了支持同主机两个进程间通信,还支持同一网络内部非同一主机上的进程间进行通信。
通过一个双链表去组织PCB
(1)创建一个进程就是把对应的PCB加入到链表中。
(2)销毁一个进程就是把对应的PCB从双链表中删除。
(3)查看所有进程就是遍历这个链表。
进程就是操作系统中的核心概念
一个线程就是一个"执行流",每个线程之间都可以按照顺序执行自己的代码,多个线程之间“同时”执行多份代码。
(1)“并发线程"成为"刚需"
*单核CPU的发展遇到了瓶颈,要想要提高算力,就需要多核CPU。而并发编程更能充分利用CPU资源
*有些任务场景需要"等待IO",为了让等待IO的时间去做一些其它的工作,也需要并发编程
(2)虽然多进程也能实现并发编程,但是线程比进程更加轻量
*创建线程比创建进程更快
*销毁线程比销毁进程更快
*调度线程比调度进程更快
最后线程虽然进程更加轻量,但随着技术不断进步,随之又有了"线程池(ThreadPool)"和"协程(Coroutine)";
*进程是包含线程的,每一个进程至少有一个线程存在,即主线程。
*进程和进程之间不共享内存空间,同一个进程的线程之间共享同一个内存资源()。
*进程是系统分配资源的最小单位,线程是系统调度的最小单位。
*一个线程如果崩溃了,就会影响到进程。
线程是操作系统中的概念, 操作系统内核实现了线程这样的机制, 并且对用户层提供了一些 API 供用户使用(例如 Linux 的 pthread 库).
Java 标准库中 Thread 类可以视为是对操作系统提供的 API 进行了进一步的抽象和封装.