由于进程之间的数据需要各自持有一份,所以创建进程需要非常大的开销。
from multiprocessing import Process import time def foo(i, arg): print('say hi', i) arg.append(i) time.sleep(1) print(arg) li = [] if __name__ == '__main__': for i in range(10): p = Process(target=foo, args=(i, li)) #p.daemon = True #主进程是否等待子进程,默认为False等待 p.start() #p.join()
进程间默认是不能数据共享的,可以通过人为实现:
from multiprocessing import Process from multiprocessing import queues import multiprocessing def foo(i, arg): arg.put(i) print('say hi', i, arg.qsize()) li = queues.Queue(20,ctx=multiprocessing) if __name__ == '__main__': for i in range(10): p = Process(target=foo, args=(i, li)) p.start()
数组必须是创建时规定类型和长度
from multiprocessing import Process from multiprocessing import Array #数组 def foo(i, arg): arg[i] = i + 100 for item in arg: print(item) print('++++++++') if __name__ == '__main__': li = Array('i', 10) for i in range(10): p = Process(target=foo, args=(i, li)) p.start()
数组类型对应表:
'c': ctypes.c_char, 'u': ctypes.c_wchar, 'b': ctypes.c_byte, 'B': ctypes.c_ubyte, 'h': ctypes.c_short, 'H': ctypes.c_ushort, 'i': ctypes.c_int, 'I': ctypes.c_uint, 'l': ctypes.c_long, 'L': ctypes.c_ulong, 'f': ctypes.c_float, 'd': ctypes.c_double
from multiprocessing import Process from multiprocessing import Manager #特殊字典 def foo(i, arg): arg[i] = i+100 print(arg.values()) if __name__ == '__main__': obj = Manager() li = obj.dict() for i in range(10): p = Process(target=foo, args=(i, li)) p.start() time.sleep(0.6) # 当主进程执行完毕后,子进程与主进程的连接断开, # 所以便不能修改主进程字典,所以报错,但是可以看到几个,可一将时间修改长一些
当创建进程时(非使用时),共享数据会被拿到子进程中,当进程中执行完毕后,再赋值给原值。
进程锁:(和线程锁相同)
# 进程锁,未加锁,执行中会产生脏数据。 from multiprocessing import Array NUM = 9 #普通的数据类型是不能共享的 def foo(i, li): li[0] -= 1 global NUM NUM -= 1 time.sleep(1) print(li[0], NUM) li = Array('i', 1) li[0] = 10 if __name__ == '__main__': for i in range(10): p = Process(target=foo, args=(i, li)) p.start()
# 进程锁,已加锁,其方法与线程锁基本相同 from multiprocessing import Array from multiprocessing import RLock, Lock, Event, Condition def foo(i, li): li.acquire() li[0] -= 1 time.sleep(1) print(li[0]) li.release() li = Array('i', 1) li[0] = 10 lock = RLock() if __name__ == '__main__': for i in range(10): p = Process(target=foo, args=(i, li)) p.start()
进程池:
进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进程,那么程序就会等待,直到进程池中有可用进程为止。
进程池中有两个方法:apply和apply_async
#进程池,默认有进程池 from multiprocessing import Pool def foo(arg): time.sleep(1) print(arg) if __name__ == '__main__': pool = Pool(5) for i in range(30): # apply方法是去进程池中取进程,进程间为串行,非并行 pool.apply(func=foo, args=(i,)) #pool.apply_async(func=foo, args=(i,)) print('end')
from multiprocessing import Pool def foo(arg): time.sleep(0.1) print(arg) if __name__ == '__main__': pool = Pool(5) for i in range(30): pool.apply_async(func=foo, args=(i,)) # close方法表示所有的任务执行完毕后再继续往下执行 # pool.close() time.sleep(0.5) # terminate表示立即终止,不管任务是否执行完毕,立即终止再继续往下执行 pool.terminate() pool.join() print('end')