[01]从零开始的JAVAEE-线程与进程

目录

说在前面

什么是进程

操作系统

并发

进程管理

PCB

CPU资源相关的属性

进程的内存分配

进程间通信 

线程

线程轻量的原因

线程的特点

线程与进程的区别 



说在前面

最近正在从零开始学习JAVAEE中的多线程开发板块,所以将自己的学习过程用通俗易懂的语言总结归纳成博客记录下来,我会尽可能涵盖JAVAEE中的重点学习内容(包括八股文),目的是让一个小白通过我的博客也能熟练掌握理解JAVAEE的核心内容。​​​​​​​

什么是进程

通俗来说,进程可以理解为计算机正在运行的程序,每一个进程都有一块独立的内存空间

进程中还包含许许多多的东西

  • 程序代码
  • 数据
  • 上下文
  • 状态
  • 系统资源
  • ......

可以按ctrl+alt+.打开任务管理器,就可以看到当前计算机中正在运行的进程 

应用和后台进程都是操作系统中运行着的进程 

操作系统

操作系统的存在是为了负责管理和调度这些进程,使得他们可以正常运行,并且保证进程间不会互相干扰。

引入进程,目的就是为了可以实现多个任务并发执行这样的效果。可以按ctrl+alt+.打开任务管理器,就可以看到当前计算机中正在运行的进程

并发

并发是指同时执行多个任务或操作的能力,在我以前的文章中举过一个餐馆的例子

一个餐馆有许多桌客人就餐,这就是一个并发过程,将餐馆比作操作系统,那么每一个桌子就代表一个进程,在桌子上就餐的客人就是一个线程。桌子需要餐馆来配备相关资源(服务员、厨房、餐具等),多个桌子同时就餐互不干扰,这就是并发的过程。请记住这个案例。线程会在后面详细介绍

进程管理

通常我们描述一个进程,都使用一个结构体/类一个进程有哪些信息表示出来,并且使用一定的数据结构将这些把这些结构体/对象放到一起进行组织
我们通常把描述进程的结构体简称为:PCB(process control block)

 注意:进程是操作系统进行资源分配的基本单位

PCB

PCB是一个用来描述进程的结构体,pcb中有很多的属性,这里只描述一些核心的结构

  • PID :每个进程的唯一身份标识
  • 内存指针:当前这个进程使用的内存是哪一部分
  • 文件描述符表:进程每打开一个文件,就会产生一个文件描述符,以此来标识这个被打开的文件,一个进程会打开许多文件,对应一组文件描述符,把这些文件描述符放到一个顺序表这样的结构里,就构成了文件描述符表
  • CPU资源相关的属性,这些属性都是辅助进行进程调度的

CPU资源相关的属性

  • 进程状态:就绪态:已经准备好的进程,随时可以上cpu执行 / 阻塞态:暂时无法上cpu执行的进程
  • 进程的优先级:进程间的调度不一定是公平的,有一定的优先级
  • 进程的上下文:描述当前进程执行到哪里的存档记录
  • 进程的记账信息:统计每个进程在cpu上执行多久来作为调度的参考依据 操作系统往往使用双向链表来组织pcb:

操作系统往往使用双向链表来组织PCB

  • 创建一个进程,就是创建链表的结点
  • 销毁一个进程,就是删除链表的结点
  • 遍历进程列表,就是遍历链表

进程的内存分配

操作系统给进程分配的内存,都是以”虚拟地址空间"的方式进行分配的,也就是说:每个进程访问的内存地址,都不是真实存在的物理内存的地址
如果每个进程都可以直接访问物理内存的地址,那么会产生这样的问题

例如出现一个进程出现代码bug:越界,那么这个进程就可能会直接影响另一个进程的状态,即a的bug导致b的bug。

所以为了避免这种情况发生,在操作系统中往往使用虚拟空间地址

两个进程访问的内存会被一个页表映射到真实的物理内存上,这样两个进程互不感知,自然也就无法互相影响。

站在这两个进程的角度来看,他们代码中操作的内存地址就是0x00-0xff这一区间,他们访问的内存会被页表直接映射到真实物理地址上,而这两个进程自身是感知不到真实物理内存地址的,这样就规避了风险,如果进程1产生野指针,或越界等bug,此时页表无法翻译这些bug,也就无法修改真正的物理内存,从而不会对别的物理内存进行干扰。 页表的最大目的就是为了方便校验:知道当前的地址是否有效 所以就可以引出进程的性质之一:独立性,这大大提示了操作系统的稳定性 

页表的最大目的就是为了方便校验:知道当前的地址是否有效
所以就可以引出进程的性质之一:独立性,这大大提示了操作系统的稳定性

进程间通信 

由于进程相互独立无法相互感知,这就导致了进程间无法直接进行通信,无法交互完成数据的操作。

为了解决这个问题:进程间就找到了一个公共区域,两个进程借助这个区域来完成数据交换。这是在隔离性的前提下做出一些妥协的。

注意:在java中其实是不鼓励多进程编程的,但也并非完全没有。

线程

在上文描述的进程,其实是比较“重量的”。它的速度慢,消耗资源高。在对进程进行创建、消耗、调度时,成本都是比较高的,进程之所以重量,是因为它涉及到资源分配,而资源分配是一个非常耗时的操作。比如系统给进程分配一块空闲空间,首先要对自身进行遍历,找到一块大小差不多的空间进行分配,而这个遍历的时间是相对较长的。而且同时会有很多进程向系统申请资源。

线程,相对于进程来说,就是一个相对轻量的东西。如果进程是一块内存空间,那么线程就是这块内存空间里的一个执行流,比如进程是一个工厂,那么线程就是工厂中的生产线,如果要扩大生产,是在原有的工厂中增加生产线,还是另辟一块空间在新建一个工厂,其成本和效率一目了然。 多个线程之间也是并发执行的

还记得上面提到的餐馆的案例吗?如果餐桌是进程,那么在餐桌上吃饭的人就是线程,没有进程就没有线程,线程是包含在进程中的

线程轻量的原因

一个进程中的多个线程之间,共用一份系统资源:内存空间、文件描述符表。 一旦第一个进程创建完毕,后续在进行线程创建,就不必进行系统资源申请了。这样效率提高了很多

线程的特点

一般来说,只要系统给的资源足够多,线程是可以一直创建,没有上限的。但即便如此,线程也不是越多越好,例如一个房间放着一张桌子,桌子上有100只鸡,桌子边有10个位置。

当一个人吃的时候效率很低

 而十个人吃的时候,是效率最高的时候

而此时,如果在增加人数,就会发生拥挤,导致没吃上的人因为想吃鸡而去挤掉别的人 

而如果此时存在一个暴躁老哥,因为没吃上鸡而愤怒掀桌,就会导致一整个房间都吃不上鸡,发生混乱。

这里的例子中,鸡是系统资源,人是线程。而桌子边的数量是CPU的核心数

说明:

  • 线程并非越多越好,因为CPU的核心数量是固定的,线程过多,反而会导致效率降低。
  • 一个线程的错误,会导致整个进程的错误,即一个线程的错误可能会把全部线程都带走 

线程与进程的区别 

  • 进程包含线程
  • 线程有自己的独立内存空间和文件描述符表,同一个进程中的多个线程,共享一份地址空间和符表
  • 进程是操作系统分配资源的基本单位,线程是操作系统调度执行的基本单位。
  • 进程之间有独立性,一个进程挂了不会影响别的进程,而一个线程挂了可能会把整个进程带走,影响其他线程的
  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不卷啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值