zoukankan      html  css  js  c++  java
  • 十、多进程

    一、进程基础

    冯诺依曼体系:

    程序和系统:一个系统一般由多个程序构成。如:Win10系统由进程管理程序、内存管理程序、N个驱动程序等构成。

    操作系统的作用:与硬件交互,为用户程序提供安全、稳定的执行环境,提供大量的API供用户程序使用。

    任务:打开某个软件、浏览网页、下载电影、听音乐、玩游戏……每个应用程序被称为一个任务。

    单任务:只能有一个任务在进行(DOS系统)

    多任务:可以有多个任务同时进行(Win10系统)

    CPU时间片:程序的执行依赖于CPU,CPU把自己进行时间上的分割,每个程序轮流占用CPU。时间片一般是切换所需时间的100倍。
    0.01us 运行 A 0.02us 运行B 时间片轮转

    单核: 同一时间,只能有一个程序 在使用CPU

    分时操作系统:以时间片轮转的方式,让一台计算机为多个终端服务。 (多用户)

    进程:应用程序的动态执行过程。(Process:(为达到某一目标的)过程;进程;流程、过程、步骤;)

    • 网易云音乐 (软件)
    • cloudmusic.exe(进程)
    • 过程: 启动 -> 软件代码要加载到内存--> CPU为进程建立“档案” --> 等CPU时间片 -- > 退出
    • 软件只有运行才能生成进程
    • 1个软件可以生成1~n个进程

    二、进程的状态:运行、等待、就绪

    • PCB: 进程控制块(PCB Process Control Block),是操作系统中最重要的记录性数据结构。它是进程管理和控制的最重要的数据结构,每 一个进程均有一个PCB
    • 创建状态:进程在创建时需要申请一个空白PCB,向其中填写控制和管理进程的信息,完成资源分配。如果创建工作无法完成,比如资源无 法满足,就无法被调度运行,把此时进程所处状态称为创建状态
    • 就绪状态:Ready to run。创建进程后,进程进入就绪状态(即进程被加载到主内存中)这里的进程已经准备好运行,正在等待获取执行它的CPU时间。准备由CPU执行的进程在队列中维护以备处理。
    • 执行状态:进程由CPU选择执行,进程中的指令由任何一个可用的CPU核心执行。
    • 阻塞状态:每当进程请求访问I/O或需要用户输入,它将进入阻塞或等待状态。进程继续在主内存中等待,不需要CPU。一旦I/O操作完成,进程将进入就绪状态。
    • 终止状态:进程被终止,PCB也被删除。

    操作系统管理进程:分配内存给进程,分配CPU时间片给进程,存储进程信息(使用PID标识进程,为进程设置优先级,记录进程状态,记录I/O状态等

    如何人为地改变进程的状态:可以通过信号修改进程的状态。taskkill /f /PID 8899 taskkill /f /t /im Typora.exe 杀程序

    三、创建并执行进程

    在Python中,执行一个Python脚本,就会创建一个进程。

    可以用os.getpid()获得进程的PID

    如何创建2个进程? multiprocessing.Process创建进程

    关于daemon:

    • 设置daemon = True,主进程执行完,不会等待该进程
    • 设置daemon = False,主进程执行完,会等待该进程执行完再退出

    关于join:

    • p1.json()
    • 主进程会等p1执行完再执行剩下的代码。
    import os
    import time
    from multiprocessing import Process
    
    
    def cloudmusic():
        """模拟网易云音乐的进程"""
        for i in range(5):
            print(f"子进程{os.getpid()}正则播放 无人之岛...")
            time.sleep(1)
    
    
    def lol():
        """模拟lol进程"""
        for i in range(8):
            print(f"子进程{os.getpid()}游戏中,请勿打扰...")
            time.sleep(1)
    
    
    def process_test():
        start_time = time.time()
        # 创建网易云音乐进程
        # 在主进程中通过Process类创建的进程对象就是子进程
        p1 = Process(target=cloudmusic)
        p2 = Process(target=lol)
        # 设置daemon = True,主进程执行完,不会等待该进程
        # 设置daemon = False,主进程执行完,会等待该进程执行完再退出
        p1.daemon = True
        p2.daemon = False
        print(f"我是主进程,我的进程id是{os.getpid()}")
        p1.start()  # 启动子进程p1
        p2.start()  # 启动子进程p2
        p1.join()
        # p2.join()
        end_time = time.time()
        print(end_time - start_time)  # 这是主进程中最后1行代码,运行完,主进程结束
    
    
    if __name__ == '__main__':
        process_test()
        # start_time = time.time()
        # lol()
        # cloudmusic()
        # end_time = time.time()
        # print(end_time - start_time)

    四、进程的全局变量

    每创建一个进程,CPU都会单独分配资源

    所以,多个进程不会共享全局变量

    from multiprocessing import Process
    
    result = 0
    
    
    def work01():
        global result
        result += 1
        print(f'work01中result值是{result}')
    
    
    def work02():
        global result
        result += 1
        print(f'work02中result值是{result}')
    
    
    def main():
        work01()
        work02()
        print(result)
    
    
    def process_test():
        p1 = Process(target=work01)
        p2 = Process(target=work02)
        p1.start()
        p2.start()
        p1.join()
        p2.join()
    
    
    if __name__ == '__main__':
        process_test()
        print(f'主进程中result的值是:{result}')
    
    '''
    work01中result值是1
    work02中result值是1
    主进程中result的值是:0
    '''

    五、多进程中使用队列共享数据

    多进程中如何使用队列共享数据?

    答: 多个进程共享主进程中创建的队列即可。主进程创建队列,然后把队列当做参数传给每个子进程即可。

    from multiprocessing import Process, Queue
    
    
    def work01(q):
        print(id(q))
        r = q.get()
        r += 1
        q.put(r)
        print(f'work01中q值是{r}')
    
    
    def work02(q):
        print(id(q))
        r = q.get()
        r += 1
        q.put(r)
        print(f'work02中q值是{r}')
    
    
    def process_test():
        q = Queue()
        q.put(0)
        p1 = Process(target=work01, args=(q,))
        p2 = Process(target=work02, args=(q,))
        p1.start()
        p2.start()
        p1.join()
        p2.join()
        print(f'主进程中q的值是:{q.get()}')
    
    
    if __name__ == '__main__':
        process_test()

     六、自定义进程类

    import multiprocessing
    import time
    
    
    class MyProcess(multiprocessing.Process):
        def __init__(self,user):
            super(MyProcess, self).__init__()
            self.user = user
    
    
        def run(self):
            """进程启动的时候会调用此方法"""
            for i in range(3):
                time.sleep(1)
                print(f'{self.user}正在学习Python...')
    
    
    if __name__ == '__main__':
        p1 = MyProcess(user='小样儿')
        p2 = MyProcess(user='乐乐')
        p1.start()
        p2.start()
    
    '''
    小样儿正在学习Python...
    乐乐正在学习Python...
    小样儿正在学习Python...
    乐乐正在学习Python...
    小样儿正在学习Python...
    乐乐正在学习Python...
    '''
  • 相关阅读:
    Jquery
    JavaScript
    poj--2115 C Looooops
    poj--3970 party
    poj 1061 青蛙的约会
    hdu1250--Hat's Fibonacci
    2318--TOYS
    扩展欧几里得--让你一次刷个够
    关于大数加法的解法
    有关环形数组的约瑟夫问题
  • 原文地址:https://www.cnblogs.com/zhangjx2457/p/14129476.html
Copyright © 2011-2022 走看看