进程的创建与多进程
一、同步与异步
同步与异步:用来描述任务的提交方式
1.同步:提交完任务之后原地等待任务的返回结果,期间不做任何事
一个任务调起另一个任务的时候,会去等待其任务返回结果(或执行结束),然后再继续执行。
如下两图都是同步操作:
在Task A调用Task B后,Task A会等待Task B执行结束后,再继续执行。

2.异步:提交完任务之后不原地等待,直接去做其他事情,结果通过反馈机制获得,有结果自动通知
一个任务调起另一个任务的时候,不会去等待其返回结果(或执行结束),仍然继续执行自己的逻辑。
如下图,在Task A调用Task B后,Task A不会停止执行,Task A与Task B并行执行。
二、阻塞非阻塞
用来表达任务的执行状态
1.阻塞:任务处于阻塞态
是指调用结果返回之前,当前线程(进程)会被挂起。
在调用的结果返回之前,当前线程(进程)不会执行其他操作。
2.非阻塞:任务处于就绪态、运行态
指执行一个调用,当前线程(进程)不会挂起。
当前线程(进程)如果还有其他操作,不会影响执行。
我们常常看到的是同步与异步、阻塞非阻塞,四者的组合
三、综合使用
1.同步阻塞
效率最低,单任务按顺序执行
2.同步非阻塞
多任务,定时查看任务执行状态
3.异步阻塞
单任务,自动提交任务执行状态。
4.异步非阻塞
效率最高,提交完任务之后不原地等待,直接去做其他事情,并且cpu也不会被剥夺走。多任务,自动提交任务执行状态,合理分配,最大化利用资源。
TASK A在执行过程中调起了Task B,与Task B并行执行,因此是异步。
Task A调起Task B后,并没有挂起当前线程,因此是非阻塞。
四、创建进程的多种方式
1.方式1:鼠标双击创建进程
系统中,鼠标双击软件图标,创建进程
2.方式2:代码创建进程
python代码创建进程,使用multiprocessing模块中的类Process来创建进程
(1)生成类Process的对象创建进程
为子进程传参需要用类Process中的arg位置传参或者kwargs关键值传参,如args=('jason',18)
中,参数需要在元组中赋值给args
# 创建进程模块multiprocessing from multiprocessing import Process import time def task(name,age): print('task is running',name) time.sleep(3) print('task is over',age) if __name__ == '__main__': "让一个函数在同一时间执行多次" p1 = Process(target=task,args=('jason',18)) p1.start() # 异步操作:子进程 告诉操作系统创建一个新的进程,并在该进程中执行task函数 # task() # 同步操作 print('主进程') ==========运行结果=============== 主进程 task is running jason # 3s后 task is over 18
(2)编写类继承Process,来创建子进程
1.使用类继承Process类,来创建子进程
from multiprocessing import Process import time class MyProcess(Process): def run(self): print('run is running') time.sleep(3) print('run is over') if __name__ == '__main__': obj = MyProcess() obj.start() print('主进程') ==========运行结果=============== 主进程 run is running run is over
2.传参问题:利用__init__
实例化方法和super派生方法传参
由于Process中已经存在名为name的属性了,当仍然想用属性name的时候,需要在super方法后赋值
class MyProcess(Process): def __init__(self,name,age): super().__init__() self.name = name self.age = age def run(self,): print('run is running',self.name) time.sleep(3) print('run is over',self.age) if __name__ == '__main__': obj = MyProcess('jason',18) obj.start() print('主进程')
3.在不同的操作系统中创建进程的注意事项
由于在不同的操作系统中创建进程的底层原理不同:
在 windows 系统中,是以导入模块的形式创建进程,所以创建子进程会循环创建,直到报错。
在linux/mac 系统中, 是以拷贝代码的形式创建子进程。

总之使用 if __name__ == '__main__':
语句来创建子进程更为合适
4.进程的join方法
join方法的作用:让主进程代码等待子进程代码运行结束再执行
from multiprocessing import Process import time def task(name, n): print('%s is running' % name) time.sleep(n) print('%s is over' % name) if __name__ == '__main__': p = Process(target=task, args=('jason', 1)) # 拿类产生一个对象 p.start() # 异步 """主进程代码等待子进程代码运行结束再执行""" p.join()
拓展:join方法位置不同,运行时间不同
from multiprocessing import Process import time def task(name, n): print('%s is running' % name) time.sleep(n) print('%s is over' % name) if __name__ == '__main__': p1 = Process(target=task, args=('jason', 1)) # 拿类产生一个对象 p2 = Process(target=task, args=('jason', 2)) p3 = Process(target=task, args=('jason', 3)) """主进程代码等待子进程代码运行结束再执行""" print('主进程') start_time = time.time() p1.start() p2.start() p3.start() p1.join() p2.join() p3.join() print(time.time()-start_time) ==========运行结果=============== 3.058879852294922
当进程同时执行,然后在用join方法等待时,时间是3s
"join方法位置不同,运行时间不同" start_time = time.time() p1.start() # 对象产生进程 p1.join() p2.start() p2.join() p3.start() p3.join() print(time.time() - start_time) ==========运行结果=============== 6.190535068511963
改变join方法的位置,则结果变成6s
五、进程间数据隔离
同一台计算机上的多个进程数据上严格意义上的物理隔离(默认情况下),也就是说默认情况下进程之间无法互相传递信息
import time from multiprocessing import Process name = 1000 def task(): global name name = 'duoduo' print('子进程', name) if __name__ == '__main__': p1 = Process(target=task) p1.start() # 通过对象创建子进程 time.sleep(3) # 使主进程代码等待三秒 print(name) # 主进程代码打印变量名name =======代码运行========= 子进程 duoduo 1000
结果发现子进程运行,并不能改变主进程的变量名的值
六、ipc机制
ipc:一台计算机上的进程间通行
消息队列:存储数据的地方,公共仓库,所有人都可以存,都可以取
"当台计算机上的消息队列" from multiprocessing import Queue q = Queue(3) # 括号内可以指定存储数据的个数 # 往消息队列中存放消息 q.put(1) print(q.full()) # 判断队列是否已满返回布尔值 q.put(2) q.put(3) print(q.full()) # q.put(4) # 程序等在这里了 print(q.get()) print(q.get()) print(q.empty()) # False 判断队列是否为空 print(q.get()) # print(q.get()) # 程序等在这里了长期进入io状态 print(q.get_nowait()) # 直接报错_queue.Empty
full() ``empty()
在多进程中都不能使用,因为判断会失真,当某一个去判断的时候,立即有别的进程存取消息队列的数据,会改变消息队列的数据,此时的判断并不准确就会失真
七、生产者消费者模型
主要爬虫领域
生产者:负责产生数据的人
消费者:负责处理数据的人
该模型必须在生产者和消费者之间必须要有消息队列(能存储数据的地方也可以是文件,数据库),减少了生产者和消费者的耦合
八、进程对象的多种方法
1.如何查看进程号
from multiprocessing import Process, current_process import os def task(): # print(current_process()) # print(current_process().pid) # .pid获取当前进程的进程号 print('子', os.getpid()) print('子进程的主进程号', os.getppid()) if __name__ == '__main__': p1 = Process(target=task) p1.start() # print(current_process()) # print(current_process().pid) print('主', os.getpid()) # os.getpid()获取当前进程的进程号
2.终止进程
(1)代码实现
p1.terminate()
(2)命令行实现
3.判断进程是否存活
p1.is_alive() 光速看
4.其他
start()
九、守护进程
守护进程会随着守护的进程结束而立刻结束
当子进程是主进程的守护进程时,主进程一旦结束,那么子进程不需要手动结束也会被结束掉
from multiprocessing import Process import time def task(name): print('子进程:%s' % name) time.sleep(3) print('子进程结束') if __name__ == '__main__': p = Process(target=task, args=('运行',)) p.daemon = True # 声明p对象生成的子进程是主进程的守护进程 p.start() time.sleep(1) print('主进程结束')

十、僵尸进程与孤儿进程
1.僵尸进程
进程执行完毕后并不会立刻销毁所有的数据,会有一些信息短暂保留下来
比如一些信息:进程号、进程执行时间、进程消耗功率等会交给父进程查看
所有的进程都会变成僵尸进程的时刻
2.孤儿进程
子进程正常运行,父进程意外死亡:操作系统针对孤儿进程会派遣
福利院管理
十一、多进程数据错乱问题
模拟抢票软件:多进程操作数据很有可能会造成数据错乱>>>:互斥锁
互斥锁:将并发变成串行,牺牲了效率但是保障了数据的安全
模拟抢票软件 from multiprocessing import Process import time import json import random # 查票 def search(name): with open(r'data.json', 'r', encoding='utf8') as f: data = json.load(f) print('%s在查票 当前余票为:%s' % (name, data.get('ticket_num'))) # 买票 def buy(name): # 再次确认票 with open(r'data.json', 'r', encoding='utf8') as f: data = json.load(f) # 模拟网络延迟 time.sleep(random.randint(1, 3)) # 判断是否有票 有就买 if data.get('ticket_num') > 0: data['ticket_num'] -= 1 with open(r'data.json', 'w', encoding='utf8') as f: json.dump(data, f) print('%s买票成功' % name) else: print('%s很倒霉 没有抢到票' % name) def run(name): search(name) buy(name) if __name__ == '__main__': for i in range(10): p = Process(target=run, args=('用户%s'%i, )) p.start()
此时多进程操作数据很有可能会造成数据错乱

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY