• python-并发编程之进程


    进程

    python中创建进程模块为:multiprocessing

    开销非常大 是计算机中资源分配的最小单位(内存隔离) 能利用多个CPU 由操作系统控制 同时操作内存之外的数据会产生数据的不安全

    进程之间数据不是共享的

    注意:windowns下进程运行会报错,linux mac 不会出现此问题。解决方法:

    将进程启动代码放到main里即可执行,示例代码:

    import multiprocessing
    
    def task(arg):
        print(arg)
    
    def run():
        for i in range(10):
            # 实例化一个进程
            process = multiprocessing.Process(target=task,args=(i,)) 
            # 进程启动
            process.start()
    
    if __name__ == '__main__':
        run()  # main下才能正确执行,不然会报错
    

    进程常用方法:

    • join():和线程一样,默认会等子进程执行完毕后,代码才会继续往下执行
    • daemon:
      • True 为 主进程执行完代码,程序会直接结束,不会等待子进程执行完毕
      • False为:主进程执行完毕后,会等待子进程执行完毕
    • name:为进程起一个名称
    • multiprocessing.current_process() :获取当前进程
    • ident/pid:获取当前进程的ID号

    示例代码:

    import time
    import multiprocessing
    
    def task(arg):
        p = multiprocessing.current_process() # 获取当前进程
        print(p.name) # 打印当前进程名称
        print(p.ident) # 获取当前进程的ID号
        print(p.pid) # 获取当前进程的ID号
        time.sleep(2)
        print(arg)
    
    def run():
        print('11111111')
        #### 进程一
        process1 = multiprocessing.Process(target=task,args=(1,))
        # False 主进程执行完毕后,会等待子进程执行完毕
        # True 为不等待子进程执行完毕,主进程执行完毕后,程序就会结束
        process1.daemon = False
        # 为当前进程起一个名称
        process1.name = 'proc1'
        process1.start()
        # 默认会等进程执行完毕后,代码才会继续往下执行
        process1.join()
        
        print('22222222')
        
    	#### 进程二
        process2 = multiprocessing.Process(target=task, args=(2,))
        process2.daemon = False
        process2.name = 'proc2'
        process2.start()
        process2.join()
        
        print('33333333')
    
    if __name__ == '__main__':
        run()
    

    类继承方式创建进程(示例代码如下:)

    ##################### 类继承方式创建进程  #####################
    import multiprocessing
    
    class MyProcess(multiprocessing.Process):
        def run(self):
            print('当前进程', multiprocessing.current_process())
    
    def run():
        t1 = MyProcess()
        t1.start()
    
        t2 = MyProcess()
        t2.start()
    
    if __name__ == '__main__':
        run()
    

    进程之间的数据共享

    multiprocessing.Queue(列表数据共享)

    windows下执行数据共享有点问题,所以使用下面方法可以解决

    • 示例代码:
    ##################### 进程之间的数据共享 multiprocessing.Queue #####################
    import multiprocessing
    
    q = multiprocessing.Queue() # 数据共享可以使用的队列
    
    def task(arg,q):
        q.put(arg)
    
    def run():
        for num in range(10):
            proc = multiprocessing.Process(target=task,args=(num,q))
            proc.start()
        while True:
            v = q.get()
            print(v)
    
    if __name__ == '__main__':
        run()
    

    multiprocessing.Manger(字典数据共享)

    linux mac下可以正常执行

    示例代码:

    import multiprocessing
    
    m = multiprocessing.Manager()
    dic = m.dict()
    
    def task(arg):
        dic[arg] = 100
    
    def run():
        for num in range(10):
            proc = multiprocessing.Process(target=task,args=(num,))
            proc.start()
    
        input('>>>')
        print(dic.values())
    
    if __name__ == '__main__':
        run()
    

    windowns:

    • 第一种方法
    import multiprocessing
    
    def task(arg,dic):
        dic[arg] = 100
    
    if __name__ == '__main__':
        m = multiprocessing.Manager()
        dic = m.dict()
    
        for num in range(10):
            proc = multiprocessing.Process(target=task,args=(num,dic))
            proc.start()
            proc.join()  # 一个一个进程等待,执行完了,再执行下一个
    
        print(dic)
    
    • 第二种方法(linux也适用)
    import time
    import multiprocessing
    
    def task(arg,dic):
        time.sleep(2)
        dic[arg] = 100
    
    if __name__ == '__main__':
        m = multiprocessing.Manager()
        dic = m.dict()
    
        process_list = []
        for num in range(10):
            proc = multiprocessing.Process(target=task,args=(num,dic))
            proc.start()
    
            process_list.append(proc)
    
        while True:
            count = 0
            for p in process_list:
                if not p.is_alive():
                    count += 1
            if count == len(process_list):
                break
    
        print(dic)
    

    进程锁

    概念:不管线程还是进程,锁都是一样的

    什么时候用锁: 只有进程或线程操作同一个数据的时候才会进行加锁,如果各自做各自的是不需要加锁的

    具体意义看多线程里的锁机制,和进程一样

    多线程锁:https://www.cnblogs.com/Hybb/p/11512011.html

    锁的方法

    • Lock(一次放行一个)
    • RLock 递归锁(一次放行多个)
    • BoundedSemaphore (一次放N个) 信号量
    • Condition (1次放x个数)动态输入
    • Event (事件)1次放所有

    示例代码

    import time
    import multiprocessing
    
    lock = multiprocessing.Lock()
    lock = multiprocessing.RLock()
    lock = multiprocessing.BoundedSemaphore()
    lock = multiprocessing.Condition()
    lock = multiprocessing.Event()
    
    def task(arg):
        print('开始了')
        lock.acquire()
        time.sleep(2)
        print(arg)
        lock.release()
    
    def run():
        for num in range(1,3):
            proc = multiprocessing.Process(target=task,args=(num,))
            proc.start()
    
    if __name__ == '__main__':
        run()
    

    进程池

    使用的模块 concurrent.futures

    和线程池是一样的

    示例代码:

    import time
    # 导入进程池模块
    from concurrent.futures import ProcessPoolExecutor
    
    def task(arg):
        time.sleep(2)
        print(arg)
    
    if __name__ == '__main__':
        # 创建一个进程池
        pool = ProcessPoolExecutor(5)
        for num in range(10):
            pool.submit(task,num)
    
  • 相关阅读:
    [Linux] Nginx服务下统计网站的QPS
    [Go] go等待读取最后一行的数据内容
    [Go] Golang中的面向对象
    [Linux] 常见的并发模型
    [PHP] pmap可以查看进程占用内存的详细情况
    [PHP] 解决php中上传大文件的错误
    [PHP] 循环查看php-fpm的内存占用情况
    [Go] go中的goto语句跳到指定标签
    Java抽象类(Abstract Class)与接口(Interface)区别
    Java访问级别修饰符
  • 原文地址:https://www.cnblogs.com/Anesthesia-is/p/11977064.html
Copyright © 2020-2023  润新知