多进程面试题汇总

news2024/11/29 10:47:51

在这里插入图片描述

这里写目录标题

  • 一、多进程
    • 1、进程的定义:
    • 2、单核多任务CPU执行原理
    • 3、进程的优点和缺点
    • 4、创建进程1
    • 5、创建进程2
    • 6、进程池
      • 6.1、进程池的作用
      • 6.2、原理图
      • 6.3、使用进程池的优点
    • 7、进程间的通信(Queue)
      • 7.1、需求1:采用多进程将100加到110
      • 7.2、需求2
    • 8、进程间的通信(Pipe)
      • 8.1、Queue和Pipe的区别:
  • 二、计算(CPU)密集型和IO密集型

一、多进程

1、进程的定义:

顾名思义,就是进行中的程序。进程是python中最小的资源分配单元,进程之间的数据,资源是不共享的、是隔离的;每启动一个进程,都要独立分配资源和拷贝访问的数据;进程是重量级别的,在进程中,需要处理的问题包括进程间通信,临界区管理和进程调度,所以进程的启动和销毁的代价是比较大的。

  • 1、windows任务管理器中的每个任务都是一个进程
  • 2、进程可以直接占用CPU、内存、磁盘、网络、GPU
  • 3、打开一个浏览器就是,就是启动了一个浏览器进程;打开一个记事本,就是启动了一个记事本进程。
    在这里插入图片描述

2、单核多任务CPU执行原理

在这里插入图片描述
10年前:单核多任务cpu运行:
整个cpu分割成多个cpu时间片段,每个时间片段执行一个任务,当执行任务1时,任务2和任务3处于等待状态,因为时间片段很短毫秒级别的,所以当把时间拉长为1s时,这些任务都执行了,给人的感官是并行执行的。

3、进程的优点和缺点

优点:
1、可以使用计算机多核,进行任务的并发执行,提高执行效率,运行不受其他进程影响,创建方便
2、空间独立,数据安全
缺点:
1、进程的创建和删除消耗的系统资源较多
2、全局变量在多个进程中不能共享
3、在子进程中修改全局变量对父进程中的全局变量没有影响。因为父进程在创建子进程时对全局变量做了一个备份,父进程中的全局变量与子进程的全局变量完全是不同的两个变量。全局变量在多个进程中不能共享。

4、创建进程1

创建进程用到Process类。
p = Process(target=sub_process_run, args=('子进程1',), name="子进程1")。

  • target:运行的函数。
  • args:传入到子进程中的参数。
  • name:子进程名字。
  • 主进程:读取01创建进程.py文件,边解释边运行;当运行到第17行的时候,创建一个子进程,在已有的主进程的之上又创建了一个子进程。
  • 子进程的名字为子进程1。
  • 如果启动了子进程(p.start()),那么就调用target函数,如果函数有参数,那么就通过args中的参数进行传递。
  • p.start():启动子进程。
  • p.join():让主进程一直等待,直到p这个子进程结束。
import os
import time
from multiprocessing import Process


def sub_process_run(name):
    time.sleep(5)
    print(f'子进程的名字:{name}')
    print(f'子进程ID是:{os.getpid()}')


if __name__ == '__main__':
    print(f'主进程ID是:{os.getpid()}')
    # 创建进程,target:运行的函数
    # args:传入到子进程中的参数
    # name:子进程名字
    p = Process(target=sub_process_run, args=('子进程1',), name="子进程1")
    # 主进程:读取01创建进程py文件,边解释边运行;当运行到第17行的时候,创建一个子进程,在已有的主进程的之上又创建了一个子进程
    # 子进程的名字为子进程1
    # 如果启动了子进程(p.join()),那么就调用target函数,如果函数有参数,那么就通过args中的参数进行传递

    # 启动子进程
    p.start()
    p.join()  # 让主进程一直等待,p这个子进程结束
    print('主进程结束')

在这里插入图片描述

5、创建进程2

自定义一个进程类,需要继承Process类。
进程启动之后自动调用的函数;只有run()这块代码才是子进程执行的代码。
代码中3个进程是同时执行任务的——》多进程并行执行。
p = MyProcess(name=f"进程{i}")

  • p.start():启动子进程。
  • p.join():主进程等待3个子进程全部执行结束后,开始执行主进程。
    • join():是一个阻塞函数
    • 为什么要用列表? 10个子进程可以并行执行
  • 多线程是并发。
  • 多进程是并行。
import os
import time
from multiprocessing import Process

class MyProcess(Process):
    """
    这是定义一个自己的进程类
    """
    def __init__(self,name):
        super().__init__()
        self.name=name

    def run(self):
        """进程启动之后自动调用的函数
        只有这块代码才是子进程执行的代码
        """

        time.sleep(5)
        print(f'子进程的名字:{self.name}')
        print(f'子进程ID是:{os.getpid()}')
        print(f'子进程ID{os.getpid()}结束')



if __name__ == '__main__':
    print(f'主进程ID是:{os.getpid()}')
    process_list=[]
    # todo 3个进程是同时执行任务的——》多进程并行执行
    for i in range(3):
        # 创建子进程
        p = MyProcess(name=f"进程{i}")
        # 启动子进程
        p.start()
        process_list.append(p)

    for p in process_list:
        p.join()  # 主进程等待3个子进程全部执行结束后,开始执行主进程
    print('主进程结束')

'''
多线程是并发
多进程是并行
'''

在这里插入图片描述

6、进程池

大家思考一个问题:在一台计算机中进程可以无限制的创建吗?

6.1、进程池的作用

进程池的作用:当进程数过多,用于限制进程数。pool可以提供和指定数量的进程,供用户调用。当有新的请求提交到pool中时。如果池还没有满,那么就会创建一个新的进程来执行该请求;但如果池中的进程数已经达到规定的最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程。

6.2、原理图

绿色:子进程没有工作,处于空闲状态(子进程没有调用任务函数)
粉色:子进程处于工作状态(子进程调用了任务函数)
在这里插入图片描述
在这里插入图片描述

6.3、使用进程池的优点

1.提高效率,节省开辟进程和开辟内存空间的时间及销毁进程的时间
2.节省内存空间

进程池使用Pool类
pl = Pool(5):创建进程池,最多支持5个进程同时执行

  • Pool(5):创建多个进程,表示可以同时执行的进程数量为5个。默认大小是CPU的核心数果。
    join():进程池对象调用join,会等待进程池中所有的子进程结束完毕再去结束父进程。
    close():如果我们用的是进程池,在调用join()之前必须要先调用close(),并且在close()之后不能再继续往进程池请求

pl.apply_async(func=sub_process_run, args=(f'进程{i}',))
pl.close():进程池关闭

import os
import time
from multiprocessing import Process, Pool


def sub_process_run(name):
    """进程启动之后自动调用的函数
    只有这块代码才是子进程执行的代码
    """
    print(f'子进程的名字:{name}')
    print(f'子进程ID是:{os.getpid()}')
    print(f'子进程ID{os.getpid()}结束')
    time.sleep(5)


if __name__ == '__main__':
    print(f'主进程ID是:{os.getpid()}')
    pl = Pool(5)  # 创建进程池,最多支持5个进程同时执行
    for i in range(10): #现在有10个请求进到进程池中
        pl.apply_async(func=sub_process_run, args=(f'进程{i}',))

    pl.close()  # 进程池关闭
    pl.join()
    print('主进程结束')

注意:
因为我们Pool(4)指定了同时最多只能执行4个进程(Pool进程池默认大小是CPu的核心数),但是我们多放入了6个进程进入我们的进程池,所以程序一开始就会只开启4个进程。
而且子进程执行是没有顺序的,先执行哪个子进程操作系统说了算的。而且进程的创建和销毁也是非常消耗资源的,所以如果进行一些本来就不需要多少耗时的任务你会发现多进程甚至比单进程还要慢。

7、进程间的通信(Queue)

大家思考一下:在多进程中可以使用global+全局变量来共享数据吗?

现在设想你需要两个进程,
一个进程(接收进程)产生数据(比如从网站上爬虫,或者从websocket接收数据等),
另一个进程(转发进程)对产生的数据进行处理并转发(比如计算并处理之后上传数据库,或者发送给websocket等)。这是一个非常常见的应用场景,
直接硬写global+变量是不行的。

使用Queue类实现进程之间的通信
初始化Q对象:q=Queue()
将数据加入到队列中:q.put(100)
从队列中拿出数据:a = q.get()

进程间数据通信之Queue示意图:
在这里插入图片描述
mq.put(i) 子进程1发送数据到队列Queue中,子进程2和子进程3从队列中获取数据
Queue可以称为通信的中间件

7.1、需求1:采用多进程将100加到110

import os
import time
from multiprocessing import Process, Pool,Queue

'''
进程池中不能用Queue
'''

def sub_process_run(name,q):
    """进程启动之后自动调用的函数
    只有这块代码才是子进程执行的代码
    """
    print(f'子进程的名字:{name}')
    print(f'子进程ID是:{os.getpid()}')
    print(f'子进程ID{os.getpid()}结束')
    time.sleep(5)
    #从队列中拿出数据
    a = q.get()
    a += 1
    q.put(a)
    print(f'子进程{os.getpid()}结束,a的值为{a}')


if __name__ == '__main__':
    q=Queue()
    #将数据加入到队列中
    q.put(100)
    print(f'主进程ID是:{os.getpid()}')

    pl=[]
    # todo 3个进程是同时执行任务的——》多进程并行执行
    for i in range(10):
        # 创建子进程
        p = Process(target=sub_process_run,args=(f'进程{i}',q))
        # 启动子进程
        p.start()
        pl.append(p)

    for p in pl:
        p.join()  # 主进程等待3个子进程全部执行结束后,开始执行主进程
    print('主进程结束')

"""
阻塞函数有哪些?join、recv
"""

在这里插入图片描述

7.2、需求2

我们有两个进程,一个进程负责写(write)一个进程负责读(read)。当写的进程写完某部分以后要把数据交给读的进程进行使用,这时候我们就需要使用到了multiprocessing模块的Queue (队列):write(将写完的数据交给队列,再由队列交给read()
在这里插入图片描述
在这里插入图片描述
mq.put(i) writer进程负责把数据写入Queue
mq.get(True) 负责从Queue中读取数据,get函数是一个阻塞的函数,当队列中没有数据时,会一直阻塞在这里。
pr.terminate() 强制杀死pr进程

8、进程间的通信(Pipe)

Pipe直译过来的意思是"管"或"管道",该种实现多进程编程的方式,和实际生活中的管〈管道)是非常类似的。通常情况下,管道有2个口,而Pipe 也常用来实现2个进程之间的通信,这2个进程分别位于管道的两端,—端用来发送数据,另一端用来接收数据。
1、导入:from multiprocessing import Pipe
2、进程间数据通信之Pipe示意图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
1、p1,p2=Pipe():Pipe创建之后得到管道的两端,必须这样写,不能写成(p1=Pipe(),p2=Pipe())
2、self.pipe.send(i) :write进程负责把数据通过管道发送给另一个进程
3、value=self.pipe.recv():当管道中没有数据,该行代码一直阻塞
4、recv函数是阻塞函数

8.1、Queue和Pipe的区别:

Queue:实现多个进程之间通信的
Pipe:实现1对1,单个进程之间的通信

二、计算(CPU)密集型和IO密集型

计算密集型任务的特点是要进行大量的计算,消耗CPU资源,比如计算圆周率、浮点运算、对视频进行高清解码(每一帧是一张图片,一秒钟有25帧,也就是说视频的每秒有25张图片,一张图片又有很多的像素)等等,全靠CPU的运算能力。

  • 计算密集型应该充分使用CPU资源,那就需要使用多进程

这种计算密集型任务虽然也可以用多任务完成,但是任务越多,花在任务切换的时间就越多,CPU执行任务的效率就越低,所以,要最高效地利用CPU,计算密集型任务同时进行的数量应当等于CPU的核心数。

第二种任务的类型是IO(Input、Output)密集型,涉及到网络、磁盘IO的任务都是IO密集型任务,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度)。对于IO密集型任务,任务越多,CPU效率越高,但也有一个限度。常见的大部分任务都是IO密集型任务,比如Web应用。


在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1450171.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue axios 请求后端无法传参问题

vue请求后端无法传参问题 问题描述处理过程总结 问题描述 在学习vue时,使用axios调用后端,发现无法把参数正确传到后端,现象如下: 使用vue发起请求,浏览器上已经有传参,但是后端没接收到对应的用户名密码&…

物流|基于Springboot的物流管理系统设计与实现(源码+数据库+文档)

物流管理系统目录 目录 基于Springboot的物流管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员和管理员功能实现 (1)用户管理 (2)公告信息管理 (3)物流信息管理 (…

希捷EXOS X 5U84存储数据恢复案例

一、案例背景 希捷EXOS X 5U84是一款高性能的企业级存储设备,常用于数据中心、云计算等领域。然而,即使使用最先进的存储设备,数据丢失的风险仍然存在。下面我们将介绍一起希捷EXOS X 5U84数据恢复案例。 天津某检测中心使用了希捷EXOS X 5U8…

【51单片机】利用STC-ISP软件工具【定时器计算器】配置【定时器】教程(详细图示)(AT89C52)

前言 大家好吖,欢迎来到 YY 滴单片机系列 ,热烈欢迎! 本章主要内容面向接触过单片机的老铁 主要内容含: 欢迎订阅 YY滴C专栏!更多干货持续更新!以下是传送门! YY的《C》专栏YY的《C11》专栏YY的…

哈希切分

目录 一 二 三 2.单个子文件太大怎么办?(分两种情况讨论) 一 这样的题目典型就是KV模型的问题,即通过key IP找对应的value 出现次数,对于KV模型的问题首先想到的就是用map来统计次数,但是100G大小的文件…

《合成孔径雷达成像算法与实现》FIgure6.20

% rho_r c/(2*Fr)而不是rho_r c/(2*Bw) % Hsrcf exp函数里忘记乘pi了 clc clear close all参数设置 距离向参数设置 R_eta_c 20e3; % 景中心斜距 Tr 2.5e-6; % 发射脉冲时宽 Kr 20e12; % 距离向调频率 alpha_os_r 1.2; …

《合成孔径雷达成像算法与实现》Figure6.18

% rho_r c/(2*Fr)而不是rho_r c/(2*Bw) % Hsrcf exp函数里忘记乘pi了 clc clear close all参数设置 距离向参数设置 R_eta_c 20e3; % 景中心斜距 Tr 2.5e-6; % 发射脉冲时宽 Kr 20e12; % 距离向调频率 alpha_os_r 1.2; …

C++ bfs反向搜索(五十七)【第四篇】

今天我们来学习bfs的反向搜索。 1.反向搜索 反向搜索:是从目标状态出发进行的搜索,一般用于终点状态唯一,起点状态有多种,且状态转移是可逆的(无向边)情况。 例题:在一个长度为 n 的坐标轴上&a…

IDEA工程与模块管理

一、IDEA项目结构 层级关系: project(工程) - module(模块) - package(包) - class(类)具体的: 一个project中可以创建多个module一个module中可以创建多个package一个package中可以创建多个class二、Project和Module的概念 在 IntelliJ IDEA 中&…

round sphere around ground background space-around space-between space-evenly

round sphere around ground background space-around space-between space-evenly round around ground surround round sphere around ground background around surround around evenly between space-around space-between space-evenly Round: 描述形状为圆形或球形的。例…

Unity基础 -- 更新中(2.15)

Unity基础 文章目录 Unity基础3D数学 -- 基础一些方法插值运算三角函数坐标系 3D数学 -- 向量理解常用函数线性插值 3D数学 -- 四元数看向四元数计算 延迟函数协同程序 3D数学 – 基础 一些方法 float value01 Mathf.PI; // Π int value03 Mathf.Abs(-2); // 绝对值 int v…

OAuth 2.0 协议介绍【实现 GitHub 第三方登录】

OAuth(是 Open Authorization 开放授权的缩写),在全世界得到广泛应用,目前的版本是2.0版。 本文会对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料为RFC 6749。 OAuth 2.0 是一个开放标准&#…

Kubernetes安装部署 2

Kubeadm创建集群 如上所示,在阿里云的香港地域的ECS服务器上拉取下载Kubernetes官方提供的容器镜像 如上所示,在阿里云的香港地域的ECS服务器保存镜像到本地 Node A服务器的IP地址:192.168.0.130 端口号6443开放、部署Docker容器引擎、支持cr…

Lua: 一门轻量级、高效的脚本语言

Lua: 一门轻量级、高效的脚本语言 在当今软件开发的领域中,寻找一门既灵活又高效的脚本语言,一直是开发者们追求的目标。Lua作为一门小巧、高效、可嵌入的脚本语言,已经成为了众多开发者的首选之一。无论是游戏开发、嵌入式系统、Web 开发还是…

linux安装mysql8且初始化表名忽略大小写

mysql8下载地址 MySQL8.0安装步骤 1、把安装包上传到linux系统,解压、重命名并移动到/usr/local/目录: cd ~ tar -xvf mysql-8.0.32-linux-glibc2.12-x86_64.tar.xz mv mysql-8.0.32-linux-glibc2.12-x86_64/ mysql80/ mv mysql80/ /usr/local/2、在M…

Linux 基础/子目录分配/文件路径

在Linux系统中,整个系统只具有一个根目录“/”,用斜杠表示。根目录是整个文件系统的顶层目录,在他下面可以创建其他的目录和文件。 Linux中的子目录分配: /bin - 基本命令的二进制文件,这些命令可供所有用户使用&am…

互联网加竞赛 基于生成对抗网络的照片上色动态算法设计与实现 - 深度学习 opencv python

文章目录 1 前言1 课题背景2 GAN(生成对抗网络)2.1 简介2.2 基本原理 3 DeOldify 框架4 First Order Motion Model5 最后 1 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 基于生成对抗网络的照片上色动态算法设计与实现 该项目较为新颖&am…

嵌入式中数字音频信号传输协议:I2S协议实现

介绍 I2S(Inter—IC Sound)总线, 又称集成电路内置音频总线,是飞利浦公司为数字音频设备之间的音频数据传输而制定的一种总线标准。 采用沿独立的导线传输时钟与数据信号的设计,通过分离数据和时钟信号,避免了时差诱发的失真。 支持全双工/半…

事务及在SpringBoot项目中使用的两种方式

1.事务简介 事务(transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。 事物的四大特性: 原子性(Atomicity)&#xf…

编程和计算机基础

编程 编程:就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程。 计算机程序:是计算机所执行的一系列的指令集合,而程序全部都是用我们所掌握的语言来编写的,所以人们控制计算机一…