一宿君

V1

2022/08/06阅读:3主题:默认主题

Java并发编程系列(一)进程与线程的概念

本期内容包含以下几点:

  • 什么是进程?
  • 什么是线程?
  • 多进程的方式也可以实现并发,为什么还要使用多线程?

最初的计算机只能接受一些特定的指令,用户每输入一个指令,计算机就做出一个操作。当用户在思考或者输入时,计算机就在等待。这样效率非常低下,可想而知在很多时候,计算机都处在等待状态。

批处理操作系统

后来有了批处理操作系统,把一系列需要操作的指令写下来,形成一个清单列表,一次性交给计算机。用户将多个需要执行的程序写在磁带上,然后交由计算机去读取并逐个执行这些程序,并将输出结果写在另一个磁带上。

批处理操作系统在一定程度上提高了计算机的效率,但是由于批处理操作系统的指令运行方式仍然是串行的,内存中始终只有一个程序在运行,后面的程序需要等待前面的程序执行完成后才能开始执行,而前面的程序有时会由于I/O操作、网络等原因阻塞,所以批处理操作效率也不高

什么是进程?

人们对于计算机的性能要求越来越高,现有的批处理操作系统并不能满足人们的需求,而批处理操作系统的瓶颈在于内存中只存在一个程序,那么内存中能不能存在多个程序呢?这是人们亟待解决的问题。

于是,科学家们提出了进程的概念。

进程就是应用程序在内存中分配的空间,也就是正在运行的程序,各个进程之间互不干扰。同时进程保存着程序每一个时刻运行的状态。

程序:用某种编程语言(java、python等)编写,能够完成一定任务或者功能的代码集合,是指令和数据的有序集合,是一段静态代码

此时,CPU采用时间片轮转的方式运行进程:CPU为每个进程分配一个时间段,称作它的时间片。如果在时间片结束时进程还在运行,则暂停这个进程的运行,此时操作系统将CPU分配给另一个进程(这个过程叫做上下文切换)。如果进程在时间片结束前阻塞或结束,则CPU立即进行切换,不用等待时间片用完。

当进程暂停时,它会保存当前进程的状态(进程标识,进程使用的资源等),在下一次切换回来时根据之前保存的状态进行恢复,接着继续执行。

使用进程+CPU时间片轮转方式的操作系统,在宏观上看起来同一时间段执行了多个任务,换句话说,进程让操作系统的并发执行成为了可能。虽然并发从宏观上看有多个任务同时在执行,但在事实上,对于单核CPU来说,任意具体时刻都只有一个任务在占用CPU资源。

对操作系统的要求进一步提高

虽然进程的出现,使得操作系统的性能大大提升,但是随着时间的推移,人们并不满足一个进程在一段时间只能做一件事情,如果一个进程有多个子任务时,只能逐个的执行这些子任务,显然这很影响实际的效率。

比如杀毒软件在检测用户电脑时,如果在某一项检测中卡住了,那么后面的检测项也会受到影响。或者说当你使用杀毒软件中的扫描病毒功能时,在扫描病毒结束之前,无法使用杀毒软件中清理垃圾的功能,这显然无法满足人们的要求。

什么是线程?

那么能不能让这些子任务同时执行呢?于是人们又提出了线程的概念,让一个线程执行一个子任务,一个进程包含多个线程,每个线程负责一个单独的子任务。

使用线程之后,事情就变得简单多了。当用户使用扫描病毒功能时,就让扫描病毒这个线程去执行。同时,如果用户又使用清理垃圾功能,那么可以先暂停扫描病毒线程,先响应用户的清理垃圾的操作,让清理垃圾这个线程去执行。响应完后再切换回来,接着执行扫描病毒线程。

注意:操作系统是如何分配时间片给每一个线程的,涉及到线程的调度策略,有兴趣的同学可以看一下《操作系统》,本文不做深入详解。

现代操作系统调度的最小单元就是线程,也叫作轻量级进程。

现代操作系统在运行一个程序时,会创建一个进程,一个进程里可以创建多个线程(这些线程都拥有各自的计数器、堆栈和局部变量等属性,并且能够访问所在进程共享的内存变量),而一个线程在一个时刻只能运行在一个核心处理器上。

使用多线程的主要原因有以下三点。

(1)更多的处理器核心

试想一下,一个单线程程序在运行时只能使用一个处理器核心,那么也就是说在这个程序运行过程中,无论添加多少个处理器核心,都无法提高该程序的执行效率,因为其他的处理器核心派不上用场。相反,如果该程序使用多线程技术运行,将计算逻辑产生的子任务随各个线程分配到多个处理器核心上,可以认为是并发执行多个线程,这样就会显著降低程序的执行时间。

关于处理器核心:我们常接触到的就是手机,在近几年手机的快速发展中,在购买手机的时候经常会听到关于手机的CPU是四核处理器、八核高频处理器等等,其实这就是为了保障我们在使用手机打游戏或者同时运行多个应用程序时,不会出现卡顿的现象。

(2)更快的响应时间

一个应用程序包含多个子任务,由多个线程并行处理,加快程序执行响应速度,提升用户的体验。

(3)更好的编程模型

Java为多线程编程提供了良好并且一致的编程模型,使开发人员在面对问题时,能够专注于面对解决问题建立合适的编程模型,而不是绞尽脑汁的考虑如何将程序多线程化(线程不是越多越好)。

总之,进程和线程的提出极大的提高了操作系统的性能。进程让操作系统的并发性成为了可能,而线程让进程的内部并发成为了可能。

思考:多进程的方式也可以实现并发,为什么还要使用多线程?

多进程方式确实可以实现并发,但使用多线程,有以下几个好处:

  • 进程间的通信比较复杂,而线程间的通信比较简单,通常情况下,我们需要使用共享资源,这些资源在线程间的通信比较容易。
  • 进程是重量级的,而线程是轻量级的,故多线程方式的系统开销相对更小。

进程是一个独立的运行环境,而线程是在进程中执行的一个任务。他们两个本质的区别是是否单独占有内存地址空间及其它系统资源(比如I/O)

  • 进程单独占有一定的内存地址空间,所以进程间存在内存隔离,数据是分开的,数据共享复杂但是同步简单,因为各个进程之间互不干扰;而线程共享所属进程占有的内存地址空间和资源,数据共享简单,但是同步复杂。
  • 进程单独占有一定的内存地址空间,一个进程出现问题不会影响其他进程,不影响主程序的稳定性,可靠性高;一个线程崩溃会影响所属进程,而某个进程崩溃可能会影响整个程序的稳定性,可靠性较低。
  • 进程单独占有一定的内存地址空间,进程的创建和销毁不仅需要保存寄存器和栈信息,还需要资源的分配回收以及页调度,开销较大;线程只需要保存寄存器和栈信息,开销较小。

另外一个重要区别是,**进程是操作系统进行资源分配的基本单位,而线程是操作系统进行调度的最小单位**,即CPU分配时间的单位 。


内容总结来源以下文章:


专注于Java基础、进阶、面试以及计算机基础知识分享🐳。偶尔认知思考、日常水文🐌。
公众号二维码
公众号二维码
随和的皮蛋桑
随和的皮蛋桑

分类:

后端

标签:

后端

作者介绍

一宿君
V1

Java开发工程师