zoukankan      html  css  js  c++  java
  • python多进程(一)

    操作系统进程


    Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊。普通的函数调用,调用一次,返回一次,但是fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。子进程永远返回0,而父进程返回子进程的ID。这样做的理由是,一个父进程可以fork出很多子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用getppid()就可以拿到父进程的ID。
    进程是程序在计算机上的一次执行活动。当你运行一个程序,你就启动了一个进程。显然,程序是死的(静态的),进程是活的(动态的)。进程可以分为系统进程和用户进程。凡是用于完成操作系统的各种功能的进程就是系统进程,它们就是处于运行状态下的操作系统本身。所有由你启动的进程都是用户进程。
    通俗地讲,在操作系统的管理下,所有正在运行的进程轮流使用CPU,每个进程允许占用CPU的时间非常短(比如10毫秒),这样用户根本感觉不出来CPU是在轮流为多个进程服务,就好象所有的进程都在不间断地运行一样。但实际上在任何一个时间内有且仅有一个进程占有CPU。

    多进程


    多进程和多线程的区别
    多线程使用的是cpu的一个核,适合io密集型。
    多进程使用的是cpu的多个核,适合运算密集型。

    Multiprocessing支持子进程,通信,共享数据,执行不同形式的同步,提供了Process,Pipe, Lock等组件。

    Process

    创建一个Process对象

    p = multiprocessing.Process(target=worker_1, args=(2, ))

    target = 函数名字
    args = 函数需要的参数,以tuple的形式传入
    注意: 单个元素的tuple的表现形式(元素,)有一个逗号

    multprocessing用到的两个方法
    cpu_count()          统计cpu总数
    active_children()   获得所有子进程

    Process的对象常用方法

    is_alive()    判断进程是否存活
    run()           启动进程
    start()         启动进程,会自动调用run方法,这个常用
    join(timeout) 等待进程结束或者直到超时

    Process的常用属性

    name 进程名字
    pid 进程的pid

    相关代码示例

    import multiprocessing
    
    import time
    
    
    def worker(args, interval):
        print("start worker {0}".format(args))
        time.sleep(interval)
        print("end worker {0}".format(args))
    
    def main():
        print("start main")
        p1 = multiprocessing.Process(target=worker, args=(1, 1))
        p2 = multiprocessing.Process(target=worker, args=(2, 2))
        p3 = multiprocessing.Process(target=worker, args=(3, 3))
        p1.start()
        p2.start()
        p3.start()
        print("end main")
    
    if __name__ == '__main__':
        main()
    
    结果:
    start main
    end main
    start worker 1
    start worker 3
    start worker 2
    end worker 1
    end worker 2
    end worker 3

    p = multiprocessing.Process(target=, args=)
    target 指定的是当进程执行时,需要执行的函数
    args 是当进程执行时,需要给函数传入的参数
    注意: args必须是一个tuple, 特别是当函数需要传入一个参数时 (1,)
    p 代表的是一个多进程
    p.is_alive() 判断进程是否存活
    p.run() 启动进程
    p.start() 启动进程,他会自动调用run方法,推荐使用start
    p.join(timeout) 等待子进程结束或者到超时时间后再继续往下执行
    p.terminate() 强制子进程退出
    p.name 进程的名字
    p.pid 进程的pid

    import multiprocessing
    
    import time
    
    
    def worker(args, interval):
        print("start worker {0}".format(args))
        time.sleep(interval)
        print("end worker {0}".format(args))
    
    def main():
        print("start main")
        p1 = multiprocessing.Process(target=worker, args=(1, 1))
        p2 = multiprocessing.Process(target=worker, args=(2, 2))
        p3 = multiprocessing.Process(target=worker, args=(3, 3))
        p1.start()
        p1.join(timeout=0.5)
        p2.start()
        p3.start()
        print("the number of CPU is: {0}".format(multiprocessing.cpu_count()))
        for p in multiprocessing.active_children():
           print("The name of active children is: {0}, pid is: {1} is alive".format(p.name, p.pid))
        print("end main")
    
    if __name__ == '__main__':
        main()
    
    结果:
    start main
    start worker 1
    the number of CPU is: 4
    The name of active children is: Process-3, pid is: 9056 is alive
    The name of active children is: Process-2, pid is: 5844 is alive
    The name of active children is: Process-1, pid is: 8428 is alive
    end main
    start worker 2
    start worker 3
    end worker 1
    end worker 2
    end worker 3

    创建子进程时,只需要传入一个执行函数和函数的参数,创建一个Process实例,用start()方法启动,这样创建进程比fork()还要简单。

    Lock组件


    当我们用多进程来读写文件的时候,如果一个进程是写文件,一个进程是读文件,如果两个文件同时进行,肯定是不行的,必须是文件写结束以后,才可以进行读操作。或者是多个进程在共享一些资源的时候,同时只能有一个进程进行访问,那就要有一个锁机制进行控制。

    当多个进程需要访问共享资源的时候,Lock可以用来避免访问的冲突。主要用到了lock.acquire() 和lock.release()

    import time
    
    import multiprocessing
    
    
    def add1(lock, value, number):
        with lock:
            print("start add1 number= {0}".format(number))
            for i in range(1, 5):
                number += value
                time.sleep(0.3)
                print("number = {0}".format(number))
    
    def add3(lock, value, number):
        lock.acquire()
        print("start add3 number= {0}".format(number))
        try:
            for i in range(1, 5):
                number += value
                time.sleep(0.3)
                print("number = {0}".format(number))
        except Exception as e:
            raise e
        finally:
            lock.release()
            pass
    
    if __name__ == '__main__':
        print("start main")
        number = 0
        lock = multiprocessing.Lock()
        p1 = multiprocessing.Process(target=add1, args=(lock, 1, number))
        p3 = multiprocessing.Process(target=add3, args=(lock, 3, number))
        p1.start()
        p3.start()
        print("end main")
    
    结果:
    start main
    end main
    start add3 number= 0
    number = 3
    number = 6
    number = 9
    number = 12
    start add1 number= 0
    number = 1
    number = 2
    number = 3
    number = 4

    共享内存


    python的multiprocessing模块也给我们提供了共享内存的操作。
    一般的变量在进程之间是没法进行通讯的,multiprocessing给我们提供了Value和Array模块,他们可以在不通的进程中共同使用,Value 和 Array 都需要设置其中存放值的类型,d 是 double 类型,i 是 int 类型。

    import time
    
    import multiprocessing
    
    from multiprocessing import Value, Array, Manager
    
    
    def add1(value, number):
        print("start add1 number= {0}".format(number.value))
        for i in range(1, 5):
            number.value += value
            print("number = {0}".format(number.value))
    
    def add3(value, number):
        print("start add3 number= {0}".format(number.value))
        try:
            for i in range(1, 5):
                number.value += value
                print("number = {0}".format(number.value))
        except Exception as e:
            raise e
    
    if __name__ == '__main__':
        print("start main")
        number = Value('d', 0)
        p1 = multiprocessing.Process(target=add1, args=(1, number))
        p3 = multiprocessing.Process(target=add3, args=(3, number))
        p1.start()
        p3.start()
        print("end main")
    
    结果:
    start main
    end main
    start add1 number= 0.0
    number = 1.0
    number = 2.0
    number = 3.0
    number = 4.0
    start add3 number= 4.0
    number = 7.0
    number = 10.0
    number = 13.0
    number = 16.0
  • 相关阅读:
    [ECNU 1624] 求交集多边形面积
    [转] Java之ACM速成
    [swustoj 191] 迷宫逃离
    [Swustoj 24] Max Area
    PICK定理模板
    [HDU 1007] Quoit Design
    [转] 最近点对距离问题
    [POJ 2184] Cow Exhibition
    SGU 144.Meeting
    SGU 143.Long Live the Queen(女王万岁)
  • 原文地址:https://www.cnblogs.com/yangjian319/p/9064665.html
Copyright © 2011-2022 走看看