【线程基础】进程和线程

一.进程

进程就是操作系统提供的一种“软件资源”。我们现在所用的系统,都属于是“多任务操作系统”,就是说同一时刻,可以运行多个任务/进程。每个任务在执行过程中,都需要消耗一定的硬件资源。进程是系统分配资源的基本单位。

1.操作系统的进程管理

  1. 先描述(使用类/结构体这样的方式实现,把实体属性表示出来)
    表示进程信息的结构体,叫做PCB(进程控制块,Process Control Block)。
  2. 再组织(使用一定的数据结构,把这些结构体/对象串到一起)
    • 当我们看到任务管理器中的这些进程的时候,意味着系统内部就在遍历链表,并且打印每个节点的相关信息。
    • 如果运行一个新的程序,系统中就会多一个进程。多的这个进程就需要构造出一个新的pcb,并且添加到链表上。
    • 如果关掉一个程序,就需要把对应进程的pcb从链表中删除,并且销毁掉对应的pcb资源。
      事实上使用的数据结构不是链表,而是一个更复杂的链式结构。
      在这里插入图片描述

2.PCB的核心属性

属性功能
pidpid是进程的身份标识(同一机器同一时刻不重复)
内存指针(一组)描述这个进程能使用哪些内存(指令和数据),每个进程只能使用自己申请的内存
文件描述符表描述了进程所涉及的硬盘相关资源
CPU描述该进程所消耗的时间占CPU总运行时间的比例
状态描述某个进程是否能够去CPU上执行(就绪状态、阻塞状态(比如说加锁、等待用户输入))
优先级多个进程等待系统调度,调度的先后关系(先后、时长)
记账信息统计每一轮各个进程占用CPU的时间,根据统计结果来调整下一轮次CPU的分配,防止某个进程完全分配不到CPU
上下文支撑进程调度的重要属性,相当于游戏中的存档和读档
  • 存档:在当前进程被调度出CPU之前,把当前寄存器中的这些信息,单独保存到一个地方。
  • 读档:在该进程下次再去CPU上执行的时候,再把这些寄存器的信息给恢复回来。
  • 操作系统将硬盘这样的设备,封装成了文件。一个进程要想操作文件,需要先“打开文件”,就是让进程在文件描述符表中分配一个表项,来表示这个文件的相关信息。
2.1 CPU分配——进程调度(Process Scheduling)

如何理解PCB中的CPU属性?
前面说到,CPU就是描述执行该进程的时间占CPU运行时间的比例。

CPU有数十个核心,每个核心都可以单独执行一个进程。但我们的电脑上不止数十个进程,那就意味着如果每个进程霸占一个核心,就会导致核心不够用的情况。那么CPU是如何解决这个问题的呢?

首先要清楚一个概念,在同一时刻一个核心只可以执行一个进程;但在不同时刻,同一核心就能执行不同的进程,也就是说在不同时刻可以执行不同的进程。
那可以先执行完一个进程,再执行别的进程吗,这显然也是不合理的。如果这样,一个电脑上不能同时存在 超过逻辑核心数 的进程,然而我们的电脑上有成百上千个进程,所以只能是进行分时复用。也就是并发执行:

  1. 先讨论单个核心的情况:
    让这个核心先执行进程1的代码,执行一会儿之后,让进程1下来,再执行进程2的代码,进程2执行一段时间之后,让进程2下来,再让进程1上。每次执行都不一定能将该进程的指令执行完。
    只要切换速度够快,人是感知不到切换的过程的。也就是说,在人肉眼看来,多个进程是在同时执行的。这就是并发
  2. 现有的CPU都是多核的:
    在单个核心并发处理多个进程的同时,多个核心还可以并行执行多个进程。
  3. 并行和并发同时存在,统称为并发。

所以说,PCB中的CPU属性,是执行时间占比。

2.2 内存分配——内存管理

不同进程使⽤内存中的不同区域,互相之间不会⼲扰。

2.3 进程间通信

现代的应⽤,要完成⼀个复杂的业务需求,往往⽆法通过⼀个进程独⽴完成,总是需要进程和进程进⾏配合。
所谓进程间的通信就是说:系统提供一些公共的空间(多个进程都可以访问到),让两个进程借助这种公共空间来交互数据。
目前主流操作系统提供的进程通信机制如下:

  1. 管道
  2. 共享内存
  3. ⽂件
  4. ⽹络
  5. 信号量
  6. 信号

为什么Java不鼓励多进程编程?
原因也是Java运行在JVM虚拟机上,如果要进行多进程编程,就需要启动多个JVM虚拟机,这显然是比较浪费资源的,而相对来说,多线程可以在一个JVM虚拟机上一起执行,所以Java中多线程编程运用的还是比较多的。

二.线程

有些场景下,多进程的表现不尽人意。具体就表现在需要频繁创建和销毁进程的时候。进程是系统分配资源的基本单位。频繁地创建和销毁进程就需要频繁地从内存中加载代码和数据。取指令的操作,相对于CPU执行计算,非常耗时、开销很大,主要体现在资源的申请和释放上。(这也是CPU缓存、流水线的原因)。

那线程是如何改进这一点的呢?

线程可以看作为“轻量级进程”。在进程的基础上,既保持了独立调度执行,又省去了“分配资源”、“释放资源”带来的额外开销。相对于进程,线程做到了资源共享,即多个线程共用一份内存空间(一个进程可以包含多个线程,进程是系统资源分配的基本单位)。当某个线程销毁的时候,也不会立即释放这块内存空间。
线程也使用PCB来描述,PCB中有一个重要属性,即内存指针。多个进程的内存空间不共用,多个线程(同一进程)之间的内存空间可以共用。
在这里插入图片描述
除了内存空间,多个线程还可以共享一份硬盘空间。

举个形象的例子,以吃饭为例:
在这里插入图片描述
在这个例子中,我们简单的将桌子理解为进程,将人理解为线程
面对同样一个任务,多进程需要申请多份内存空间和文件描述符表(硬盘),就相当于吃饭时给每个人支了一张桌子。
而多线程就是在共用一份内存空间和文件描述符表(硬盘),就相当于多个人围着一张桌子吃饭。
这样,我们很容易理解多进程对于频繁申请和释放资源的弊端。

那么多线程就完全优于多进程了吗?

这件事也未必,多个线程由于共用一份内存资源,容易引起线程安全问题。

三.小结

  1. 进程是包含线程的
  2. 每个线程,都是一个独立的执行流,单独的参与到CPU的调度中(线程有自己的PCB)
  3. 每个进程,有自己的资源,进程中的线程可以共用一份资源(内存空间、文件描述符表)
    进程是资源分配的基本单位,线程是调度执行的基本单位
  4. 进程和进程之间不会相互影响,如果同一个进程中的某个线程异常,可能会影响同进程的其他线程。(线程安全问题)
  5. 线程也不是越多越好,线程太多,调度开销会明显增大。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值