• Python中的进程池及进程池锁:multiprocessing.Pool及multiprocessing.Manager().Lock()


    一、.同步与异步,指结果的返回方式:
    同步,是所有的操作都做完,才返回结果。
    异步,不用等所有操作都做完,即时返回结果。

    二、.多进程与多线程的区别:

    1、多线程可以共享全局变量,多进程不能。

    2、多线程中,所有子线程的进程号相同;多进程中,不同的子进程进程号不同。

    3、线程共享内存空间;进程的内存是独立的。

    4、同一个进程的线程之间可以直接交流;两个进程想通信,必须通过一个中间代理来实现。

    5、创建新线程很简单;创建新进程需要对其父进程进行一次克隆。

    6、一个线程可以控制和操作同一进程里的其他线程;但是进程只能操作子进程。

    7、两者最大的不同在于:在多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响;而多线程中,所有变量都由所有线程共享。

    三、多线程的优势
    进程只有一个,所以分配的CPU资源是一定的,多线程只不过是轮流抢占CPU而已,并不会真正提高处理速度。这意味着,多线程的作用主要在于提高了并发数
    Python多线程相当于单核多线程,多线程有两个好处:CPU并行,IO并行,单核多线程相当于自断一臂。所以,在Python中,可以使用多线程,但不要指望能有效利用多核。如果一定要通过多线程利用多核,那只能通过C扩展来实现,不过这样就失去了Python简单易用的特点。不过,也不用过于担心,Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务。多个Python进程有各自独立的GIL锁,互不影响。

    四、进程池的概念:
    定义一个池子,在里面放上固定数量的进程,有需求来了,就拿一个池中的进程来处理任务
    等到处理完毕,进程并不关闭,而是将进程再放回进程池中继续等待任务
    如果有很多任务需要执行,池中的进程数量不够,任务就要等待之前的进程执行任务完毕归来,拿到空闲进程才能继续执行。
    也就是说,进池中进程的数量是固定的,那么同一时间最多有固定数量的进程在运行
    这样不会增加操作系统的调度难度,还节省了开关进程的时间,也一定程度上能够实现并发效果。
    代码:

    import time
    import multiprocessing
    
    
    class PrintNumber():
    
        def __init__(self, multi_num):
            self.multi_num = multi_num
    
        def run_task(self):
            sum_num = 1
            for i in range(5):
                sum_num = i
                time.sleep(1)
                print("multi_num = {}, output = {}".format(self.multi_num, sum_num))
            return self.multi_num,"ok"
    
    def myCallBack(arg):
        print(arg)
    
    if __name__ == "__main__":
        #numprocess 要创建的进程数,如果省略,将默认使用cpu_count()的值
        #initializer每个工作进程启动时要执行的可调用对象,默认为None
        #initargs传给initializer的参数组
    
        process_pool = multiprocessing.Pool()
        for i in range(3):
            a=1
            test = PrintNumber(i)
            process_pool.apply_async(test.run_task, args=(),callback=myCallBack)
        # close是不允许再向进程池中添加任务
        # 必须close+join,否则主进程跑完了,子进程还没完,就会报错
        process_pool.close()
        process_pool.join()
        print("thread join success!")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    输出:

    multi_num = 0, output = 0
    multi_num = 1, output = 0
    multi_num = 2, output = 0
    multi_num = 0, output = 1
    multi_num = 2, output = 1
    multi_num = 1, output = 1
    multi_num = 0, output = 2
    multi_num = 2, output = 2
    multi_num = 1, output = 2
    multi_num = 0, output = 3
    multi_num = 2, output = 3multi_num = 1, output = 3
    multi_num = 0, output = 4
    (0, 'ok')
    multi_num = 1, output = 4
    multi_num = 2, output = 4
    (2, 'ok')
    (1, 'ok')
    thread join success!
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    进程池加锁:

    import time
    import multiprocessing
    
    
    def get():
        for i in range(3):
            time.sleep(1)
            print(i)
    
    
    def task(lock):
        lock.acquire()   #获取锁
        get()
        lock.release()   #释放锁
    
    
    def myCallBack(arg):
        print(arg)
    
    if __name__ == "__main__":
        #numprocess 要创建的进程数,如果省略,将默认使用cpu_count()的值
        #initializer每个工作进程启动时要执行的可调用对象,默认为None
        #initargs传给initializer的参数组
        #进程池的锁需要使用Manager().Lock()
        lock=multiprocessing.Manager().Lock()
        process_pool = multiprocessing.Pool()
        for i in range(3):
            process_pool.apply_async(task, args=(lock,))
        # close是不允许再向进程池中添加任务
        # 必须close+join,否则主进程跑完了,子进程还没完,就会报错
        process_pool.close()
        process_pool.join()
    
        print("thread join success!")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    输出:

    0
    1
    2
    0
    1
    2
    0
    1
    2
    thread join success!
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 相关阅读:
    element-ui的form校验失败
    edge/chrome浏览器favicon.ico缓存问题
    飞桨Paddle动转静@to_static技术设计
    安装银河麒麟桌面系统V10【超详细图文教程】
    httprunner4学习总结6 – 手动编写测试用例
    DevUI开源经验分享:从0到1开始运营你的开源项目
    科研方法-X_LAB-方法总结和实践记录
    vue如何实现视频全屏切换
    git 给分支添加描述
    快团团对接,供货商对接团长如何做到只吸引不打扰?
  • 原文地址:https://blog.csdn.net/hh1357102/article/details/126091502