创建进程的两种方式
1.运行应用程序
2.代码创建进程(在内存中申请一块内存空间运行相应的程序代码)
# 第一种方式 from multiprocessing import Process import time def task(name): print('%s is running' % name) time.sleep(3) print('%s is over' % name) if __name__ == '__main__': p = Process(target=task, args=('QQ',)) # 创建进程对象 p.start() # 创建一个新的进程 # 第二种方式 from multiprocessing import Process import time class MyProcess(Process): def __init__(self, username): self.username = username super().__init__() def run(self): print(f'{self.username} is running') time.sleep(3) print(f'{self.username} is over') if __name__ == '__main__': p = MyProcess('QQ') p.start()
join可以让主进程等待子进程结束之后,再执行主进程
from multiprocessing import Process import time # 不使用join方法 def task(name): print(f"{name} is running") time.sleep(2) print(f"{name} is gone") if __name__ == "__main__": p = Process(target=task, args=("QQ",)) # 创建一个进程对象 p.start() # p.join() print("主进程") # 主进程 # QQ is running # QQ is gone # 使用join方法 def task(name): print(f"{name} is running") time.sleep(2) print(f"{name} is gone") if __name__ == "__main__": p = Process(target=task, args=("QQ",)) # 创建一个进程对象 p.start() p.join() print("主进程") # QQ is running # QQ is gone # 主进程 def task(name, n): print(f'{name} is running') time.sleep(n) print(f'{name} is over') if __name__ == '__main__': p1 = Process(target=task, args=('jason', 1)) p2 = Process(target=task, args=('tony', 2)) p3 = Process(target=task, args=('kevin', 3)) start_time = time.time() p1.start() p2.start() p3.start() p1.join() p2.join() p3.join() end_time = time.time() - start_time print('主进程', f'总耗时:{end_time}') # 主进程 总耗时:3.015652894973755 # 如果是一个start一个join交替执行 那么总耗时就是6s+
from multiprocessing import Process money = 999 def task(): global money money = 666 if __name__ == '__main__': p = Process(target=task) p.start() p.join() # 确保子进程代码结束再打印money print(money) # 999 # 你会发现修改不了,因为进程之间的数据默认是隔离的,但是也可以打破
# 查看进程号 1. current_process函数 from multiprocessing import Process, current_process current_process().pid # 进程号的用处之一:通过代码管理进程 windows taskkill关键字 mac/linux kill关键字 2. os模块 os.getpid() # 获取当前进程的进程号 os.getppid() # 获取当前进程的父进程号 # 杀死子进程 terminate() # 判断子进程是否存活 is_alive()
# 僵尸进程 所有的子进程在运行结束之后都会变成僵尸进程(没死透) 还保留着pid(进程号)和一些运行过程的中的记录便于主进程查看(短时间保存) 这些信息会被主进程回收(彻底死了) 1.主进程正常结束 2.调用join方法 # 孤儿进程 子进程存活着,父进程意外死亡,子进程会被操作系统自动接管
# 守护进程(daemon)即将设置为守护进程的子进程的死亡与否参考守护的对象,对象死亡则守护进程立即死亡 from multiprocessing import Process import time def task(name): print(f'{name}活着') time.sleep(3) print(f'{name}死了') if __name__ == '__main__': p = Process(target=task, args=('子进程',)) # 守护进程必须写在start前面 p.daemon = True # 子进程设置为守护进程 p.start() # p.join() print('主进程死亡') # 加入join() ''' 子进程活着 子进程死了 主进程死亡 ''' # 注释掉join() # 主进程死亡(主进程结束 子进程立刻结束)
当多个进程操作同一份数据的时候会造成数据的错乱,这个时候需要加锁处理(互斥锁)
将并发变成串行,牺牲了效率但是保障了数据的安全
互斥锁影响程序的效率可能会产生死锁,慎用!
from multiprocessing import Process, Lock mutex = lock() # 定义互斥锁 mutex.acquire() # 抢锁 mutex.release() # 放锁