首页 > 系统相关 >并发编程之多进程理论篇

并发编程之多进程理论篇

时间:2024-01-21 21:56:42浏览次数:25  
标签:队列 编程 程序 调度 阻塞 并发 进程 之多 执行

image

引言

进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。

狭义定义:进程是正在运行的程序的实例(an instance of a computer program that is being executed)。

广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。

进程的概念

什么是进程

  • 进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。
  • 进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时(操作系统执行之),它才能成为一个活动的实体,我们称其为进程。
  • 进程是操作系统中最基本、重要的概念。是多道程序系统出现后,为了刻画系统内部出现的动态情况,描述系统内部各道程序的活动规律引进的一个概念,所有多道程序设计操作系统都建立在进程的基础上。

image

引入进程原因

  • 为了提高资源利用率和系统处理能力,现阶段计算机系统都是多道程序系统,即多道程序并发执行。
  • 优化系统资源,方便计算机调度,避免系统运算紊乱。
  • 进程是一种数据结构,能够清晰的刻画动态系统的内在规律,增加程序运行时的动态性。

进程特征

  • 动态性:进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生,动态消亡的。
  • 并发性:任何进程都可以同其他进程一起并发执行。
  • 独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位。
  • 异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进。

多个不同的进程可以包含相同的程序:一个程序在不同的数据集里就构成不同的进程,能得到不同的结果;但是执行过程中,程序不能发生改变。

程序与进程的区别

  • 程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。
  • 而进程是程序在处理机上的一次执行过程,它是一个动态的概念。
  • 程序可以作为一种软件资料长期存在,而进程是有一定生命期的。
  • 程序是永久的,进程是暂时的。

并发 并行

并行(Parallelism)

并行:指两个或两个以上事件(或线程)在同一时刻发生,是真正意义上的不同事件或线程在同一时刻,在不同CPU资源呢上(多核),同时执行。

特点

  • 同一时刻发生,同时执行。
  • 不存在像并发那样竞争,等待的概念。

并发(Concurrency)

指一个物理CPU(也可以多个物理CPU) 在若干道程序(或线程)之间多路复用,并发性是对有限物理资源强制行使多用户共享以提高效率。

通俗的话来说,并发是伪并行,即看起来是同时运行。单个cpu+多道技术就可以实现并发(并行也属于并发)。

特点

  • 微观角度:所有的并发处理都有排队等候,唤醒,执行等这样的步骤,在微观上他们都是序列被处理的,如果是同一时刻到达的请求(或线程)也会根据优先级的不同,而先后进入队列排队等候执行。
  • 宏观角度:多个几乎同时到达的请求(或线程)在宏观上看就像是同时在被处理。

image

进程调度

先来先服务算法FCFS)

先来先服务调度法(First Come First Service):按照先后顺序处理事件的一种算法。
该算法既可用于作业调度,也可用于进程调度。FCFS算法比较有利于长作业(进程),而不利于短作业(进程)。由此可知,本算法适合于CPU繁忙型作业,而不利于I/O繁忙型的作业(进程)。

短时间作业调度算法SJF / SPN

短作业优先法(Shortest Job First):又称为短进程优先算法(SPN,Shortest Process Next),能有效减少平均周转时间。
该算法既可用于作业调度,也可用于进程调度。但其对长作业不利;不能保证紧迫性作业(进程)被及时处理;作业的长短只是被估算出来的。

时间片轮转算法RR

时间片轮转法(Round Robin):让每个进程在就绪队列中的等待时间与享受服务的时间成比例,也就是需要将CPU的处理时间分成固定大小的时间片,如果一个进程在被调度选中之后用完了系统规定的时间片,但又未完成要求的任务,则它自行释放自己所占有的CPU而排到就绪队列的末尾,等待下一次调度。同时,进程调度程序又去调度当前就绪队列中的第一个进程。

显然,轮转法只能用来调度分配一些可以抢占的资源。这些可以抢占的资源可以随时被剥夺,而且可以将它们再分配给别的进程。CPU是可抢占资源的一种。但打印机等资源是不可抢占的。由于作业调度是对除了CPU之外的所有系统硬件资源的分配,其中包含有不可抢占资源,所以作业调度不使用轮转法。

在轮转法中,时间片长度的选取非常重要。首先,时间片长度的选择会直接影响到系统的开销和响应时间。如果时间片长度过短,则调度程序抢占处理机的次数增多。这将使进程上下文切换次数也大大增加,从而加重系统开销。反过来,如果时间片长度选择过长,例如,一个时间片能保证就绪队列中所需执行时间最长的进程能执行完毕,则轮转法变成了先来先服务法。时间片长度的选择是根据系统对响应时间的要求和就绪队列中所允许最大的进程数来确定的。

在轮转法中,加入到就绪队列的进程有3种情况:

分给某进程的时间片用完,但进程还未完成,回到就绪队列的末尾等待下次调度去继续执行。
分给该进程的时间片并未用完,只是因为请求I/O或由于进程的互斥与同步关系而被阻塞。当阻塞解除之后再回到就绪队列。
新创建进程进入就绪队列。
如果对这些进程区别对待,给予不同的优先级和时间片从直观上看,可以进一步改善系统服务质量和效率。例如,我们可把就绪队列按照进程到达就绪队列的类型和进程被阻塞时的阻塞原因分成不同的就绪队列,每个队列按FCFS原则排列,各队列之间的进程享有不同的优先级,但同一队列内优先级相同。这样,当一个进程在执行完它的时间片之后,或从睡眠中被唤醒以及被创建之后,将进入不同的就绪队列。

多级反馈队列

多级反馈队列调度算法则不必事先知道各种进程所需的执行时间,而且还可以满足各种类型进程的需要,因而它是目前被公认的一种较好的进程调度算法。在采用多级反馈队列调度算法的系统中,调度算法的实施过程如下所述。

应设置多个就绪队列,并为各个队列赋予不同的优先级。第一个队列的优先级最高,第二个队列次之,其余各队列的优先权逐个降低。该算法赋予各个队列中进程执行时间片的大小也各不相同,在优先权愈高的队列中,为每个进程所规定的执行时间片就愈小。例如,第二个队列的时间片要比第一个队列的时间片长一倍,……,第i+1个队列的时间片要比第i个队列的时间片长一倍。
当一个新进程进入内存后,首先将它放入第一队列的末尾,按FCFS原则排队等待调度。当轮到该进程执行时,如它能在该时间片内完成,便可准备撤离系统;如果它在一个时间片结束时尚未完成,调度程序便将该进程转入第二队列的末尾,再同样地按FCFS原则等待调度执行;如果它在第二队列中运行一个时间片后仍未完成,再依次将它放入第三队列,……,如此下去,当一个长作业(进程)从第一队列依次降到第n队列后,在第n 队列便采取按时间片轮转的方式运行。
仅当第一队列空闲时,调度程序才调度第二队列中的进程运行;仅当第1~(i-1)队列均空时,才会调度第i队列中的进程运行。如果处理机正在第i队列中为某进程服务时,又有新进程进入优先权较高的队列(第1~(i-1)中的任何一个队列),则此时新进程将抢占正在运行进程的处理机,即由调度程序把正在运行的进程放回到第i队列的末尾,把处理机分配给新到的高优先权进程。

进程状态介绍

就绪(Ready)状态:当进程已分配到除CPU以外的所有必要的资源,只要获得处理机便可立即执行,这时的进程状态称为就绪状态。

执行/运行(Running)状态:当进程已获得处理机,其程序正在处理机上执行,此时的进程状态称为执行状态。

阻塞(Blocked)状态:正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态。引起进程阻塞的事件可有多种,例如,等待I/O完成、申请缓冲区不能满足、等待信件(信号)等。

三状态图解

image

代码详解

image

两对重要概念

  • 同步和异步

***描述的是任务的提交方式***
同步:任务提交之后,原地等待任务的返回结果,等待的过程中不做任何事(干等),程序层面上表现出来的感觉就是卡住了
异步:任务提交之后,不原地等待任务的返回结果,直接去做其他事情。
	那我提交的任务结果如何获取?
    任务的返回结果会有一个异步回调机制自动处理
  • 阻塞和非阻塞

***描述的是程序的运行状态***
阻塞:阻塞调用是指调用结果返回之前,当前线程会被挂起(如遇到io操作)。
非阻塞:非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前也会立刻返回,同时该函数不会阻塞当前线程。

理想状态:我们应该让我们写的代码永远处于就绪态和运行态之间切换

上述概念的组合:最高效的一种组合就是异步非阻塞

小结:

1. 同步与异步针对的是函数/任务的调用方式:同步就是当一个进程发起一个函数(任务)调用的时候,一直等到函数(任务)完成,而进程继续处于激活状态。而异步情况下是当一个进程发起一个函数(任务)调用的时候,不会等函数返回,而是继续往下执行当,函数返回的时候通过状态、通知、事件等方式通知进程任务完成。
2. 阻塞与非阻塞针对的是进程或线程:阻塞是当请求不能满足的时候就将进程挂起,而非阻塞则不会阻塞当前进程

进程的创建(了解)

但凡是硬件,都需要有操作系统去管理,只要有操作系统,就有进程的概念,就需要有创建进程的方式,一些操作系统只为一个应用程序设计,比如微波炉中的控制器,一旦启动微波炉,所有的进程都已经存在。

而对于通用系统(跑很多应用程序),需要有系统运行过程中创建或撤销进程的能力,主要分为4中形式创建新的进程

1、系统初始化(查看进程linux中用ps命令,windows中用任务管理器,前台进程负责与用户交互,后台运行的进程与用户无关,运行在后台并且只在需要时才唤醒的进程,称为守护进程,如电子邮件、web页面、新闻、打印)

2、一个进程在运行过程中开启了子进程(如nginx开启多进程,os.fork,subprocess.Popen等)

3、 用户的交互式请求,而创建一个新进程(如用户双击暴风影音)

4、 一个批处理作业的初始化(只在大型机的批处理系统中应用)

无论哪一种,新进程的创建都是由一个已经存在的进程执行了一个用于创建进程的系统调用而创建的:

1、在UNIX中该系统调用是:fork,fork会创建一个与父进程一模一样的副本,二者有相同的存储映像、同样的环境字符串和同样的打开文件(在shell解释器进程中,执行一个命令就会创建一个子进程)

2、在windows中该系统调用是:CreateProcess,CreateProcess既处理进程的创建,也负责把正确的程序装入新进程。 

关于创建的子进程,UNIX和windows

1、相同的是:进程创建后,父进程和子进程有各自不同的地址空间(**多道技术要求物理层面实现进程之间内存的隔离**),任何一个进程的在其地址空间中的修改都不会影响到另外一个进程。

2、不同的是:在UNIX中,子进程的初始地址空间是父进程的一个副本,提示:子进程和父进程是可以有只读的共享内存区的。但是对于windows系统来说,从一开始父进程与子进程的地址空间就是不同的。

进程的终止(了解)

1、正常退出(自愿,如用户点击交互式页面的叉号,或程序执行完毕调用发起系统调用正常退出,在linux中用exit,在windows中用ExitProcess)

# 正常退出示例
import sys

sys.exit()

2、出错退出(自愿,python a.py中a.py不存在)

# 出错退出示例
try:
    result = 1 / 0
except ZeroDivisionError:
    print("Error: Division by zero")
    sys.exit(1)  # 退出并返回错误码 1

3、严重错误(非自愿,执行非法指令,如引用不存在的内存,1/0等,可以捕捉异常,try...except...)

# 严重错误示例
try:
    result = 1 / 0
except ZeroDivisionError:
    print("Error: Division by zero")
    # 这里可以进行一些处理,但无法完全修复严重错误
    raise  # 重新抛出异常,程序终止

4、被其他进程杀死(非自愿,如使用命令 kill -9 在 Linux 中强制终止进程。)

kill -9 <进程号>

进程的层次结构

无论UNIX还是windows,进程只有一个父进程。

不同的是:

在UNIX中所有的进程,都是以init进程为根,组成树形结构。父子进程共同组成一个进程组,这样,当从键盘发出一个信号时,该信号被送给当前与键盘相关的进程组中的所有成员。

在windows中,没有进程层次的概念,所有的进程都是地位相同的。唯一类似于进程层次的暗示,是在创建进程时父进程得到一个特别的令牌(称为句柄),该句柄可以用来控制子进程,但是父进程有权把该句柄传给其他子进程,这样就没有层次了。

标签:队列,编程,程序,调度,阻塞,并发,进程,之多,执行
From: https://www.cnblogs.com/xiao01/p/17978434

相关文章

  • JUC并发编程 线程中断介绍及相关Api方法
    什么是中断机制首先,一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止,自己来决定自己的命运,所以,Thread.stop,Thread.suspend,Thread.resume都已经被废弃了其次,在Java中没有办法立即停止一条线程,然而停止线程却显得尤为重要,如取消一个耗时操作。因此,Java提供......
  • Win32 编程 Windows API 使用(二)
     有了上一章的实验,我们来创建第一个自己设计的窗口按照之前的步骤,再创建一个新的项目,文件名称是app.cpp(也可以是app.c),并将这个类取名为MyApp,即最后运行的程序为MyAPP.exe 运行一遍发现这个窗口没法拖动,也没办法关闭。但是,窗口也确实显示出来了。#include<window......
  • Win32 编程 Windows API 使用(一)
    1.WindowAPI通常,Win32是指WindowsAPI,也指MicrosoftWindows操作系统的32位环境,和Win64 Windows常见环境。早期的操作系统为16位(window1.0),Win98/XP之后出现32位和64位,Win32即也是32位和64位的统称。所谓Win32编程,即主要使用GUI构图,编写一套程序。除了使用原生的Wind......
  • AOP 编程
    AOP编程目录AOP编程1.AOP和OOP2.AOP中的一些概念术语通知类型3.AOP实现方式4.AOP使用1.添加依赖:在项目的pom.xml文件中添加SpringAOP依赖,以确保AOP模块可用。2.创建切面类:创建一个Java类,并使用@Aspect注解标记它,这个类将充当切面。1.AOP和OOPAOP为AspectOrie......
  • 《Java并发实现原理:JDK源码剖析》PDF
    《Java并发实现原理:JDK源码剖析》全面而系统地剖析了JavaConcurrent包中的每一个部分,对并发的实现原理进行了深刻的探讨。全书分为8章,第1章从最基础的多线程知识讲起,理清多线程中容易误解的知识点,探究背后的原理,包括内存重排序、happen-before、内存屏障等;第2~8章,从简单到复杂,逐......
  • 《Java并发实现原理:JDK源码剖析》PDF
    《Java并发实现原理:JDK源码剖析》全面而系统地剖析了JavaConcurrent包中的每一个部分,对并发的实现原理进行了深刻的探讨。全书分为8章,第1章从最基础的多线程知识讲起,理清多线程中容易误解的知识点,探究背后的原理,包括内存重排序、happen-before、内存屏障等;第2~8章,从简单到复杂,逐......
  • A021 《斗图大赛》编程 源码
    一、课程介绍本节课将学习新的while循环,并结合布尔值True实现无限循环,最终实现一个动态表情包的效果。二、重难点解析布尔值在编程中,True是真,False是假。“真,假”,也是“对,错”的意思,它们是由英国著名数学家和逻辑学家乔治布尔提出的。所以,True和False也叫做布尔值,用于表示......
  • Python异步编程原理篇之协程的IO
    协程的IOasyncio作为实现异步编程的库,任务执行中遇到系统IO的时能够自动切换到其他任务。协程使用的IO模型是IO多路复用。在asyncio低阶API一篇中提到过“以Linux系统为例,IO模型有阻塞,非阻塞,IO多路复用等。asyncio常用的是IO多路复用模型的epool和kqueue”。本篇就介绍一......
  • 切面编程
    SpringBoot面向切面编程_springboot切面编程-CSDN博客SpringbootAOP切面编程_springboot切面编程-CSDN博客 切入点签名是什么意思切入点签名是一个包含名字和任意参数的方法签名,用于指定切入点和哪些方法进行匹配 。在AspectJ风格的AOP中,切入点签名采用一......
  • 元编程在 Python 的性能方面会有什么影响
    元编程是一种程序设计技术,它使得程序可以动态地创建和修改代码。Python作为一种动态语言,非常适合元编程。然而,使用元编程可能会对Python的性能产生一定的影响,本文将探讨这个问题。一、元编程的基本概念元编程是指在运行时创建、检查、操作和扩展程序的能力。Python中的元编程通常通......