Fork me on GitHub

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)
posted @ 2019-12-03 15:34  Anesthesias  阅读(259)  评论(0编辑  收藏  举报