并发编程:创建进程 join方法 进程间的数据隔离问题 进程对象以及其他方法 守护进程 互斥锁
创建进程的两种方式#
创建进程的过程:#
创建进程就是在内存中重新开辟一块内存空间将允许产生的代码丢进去。
一个进程对应在内存就是一块独立的内存空间进程与进程之间数据是隔离的,无法直接交互但是可以通过某些技术实现间接交互。
使用process模块时需要注意:#
在Windows操作系统中由于没有fork(linux操作系统中创建进程的机制),
在创建子进程的时候会自动 import 启动它的这个文件,而在 import 的时候又执行了整个文件。
因此如果将process()直接写在文件中就会无限递归创建子进程报错。
所以必须把创建子进程的部分使用if __name__ ==‘__main__’ 判断保护起来,import 的时候,就不会递归运行了。
第一种方式:

1 from multiprocessing import Process 2 import time 3 4 5 def test(name): 6 print('%s is running'%name) 7 time.sleep(3) 8 print('%s is over'%name) 9 10 """ 11 windows创建进程会将代码以模块的方式 从上往下执行一遍 12 linux会直接将代码完完整整的拷贝一份 13 14 15 windows创建进程一定要在if __name__ == '__main__':代码块内创建 否则报错 16 """ 17 if __name__ == '__main__': 18 p = Process(target=test,args=('egon',)) # 创建一个进程对象 19 p.start() # 告诉操作系统帮你创建一个进程 20 print('主')
第二种方式:

1 # 创建进程的第二种方式 2 from multiprocessing import Process 3 import time 4 5 6 class MyProcess(Process): 7 def __init__(self,name): 8 super().__init__() 9 self.name = name 10 11 def run(self): 12 print('%s is running' % self.name) 13 time.sleep(3) 14 print('%s is over' % self.name) 15 16 17 if __name__ == '__main__': 18 p = MyProcess('egon') 19 p.start() 20 print('主')
join方法:#
p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。
timeout是可选的超时时间,需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程
注意:多个进程同时运行(注意,子进程的执行顺序不是根据启动顺序决定的)

1 import time 2 from multiprocessing import Process 3 4 def f(name): 5 print('hello', name) 6 time.sleep(1) 7 print('我是子进程') 8 9 10 if __name__ == '__main__': 11 p = Process(target=f, args=('bob',)) 12 p.start() 13 #p.join() 14 print('我是父进程')

1 from multiprocessing import Process 2 import time 3 4 def test(name,i): 5 print('%s is running'%name) 6 time.sleep(i) 7 print('%s is over'%name) 8 if __name__ == '__main__': 9 p_list = [] 10 # for i in range(3): 11 # p = Process(target=test,args=('进程%s'%i,i)) 12 # p.start() 13 # p_list.append(p) 14 # for p in p_list: 15 # p.join() 16 p = Process(target=test,args=('egon',1)) 17 p1 = Process(target=test,args=('kevin',2)) 18 p2 = Process(target=test,args=('jason',3)) 19 start_time = time.time() 20 p.start() # 仅仅是告诉操作系统帮你创建一个进程 至于这个进程什么时候创 操作系统随机决定 21 p1.start() 22 p2.start() 23 p2.join() 24 p.join() 25 p1.join() 26 27 # 主进程代码等待子进程运行结束 才继续运行 28 # p.join() # 主进程代码等待子进程运行结束 29 print('主') 30 print(time.time() - start_time)
进程间的数据的隔离问题:#
对进程中数据修改不会影响其他进程中的数据!

1 from multiprocessing import Process 2 3 def work(): 4 global n 5 n=0 6 print('子进程内: ',n) 7 8 9 if __name__ == '__main__': 10 n = 100 11 p=Process(target=work) 12 p.start() 13 print('主进程内: ',n)
进程中的其他常用方法:#
p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁
p.is_alive():如果p仍然运行,返回True

1 from multiprocessing import Process,current_process 2 import os 3 import time 4 5 6 def test(name): 7 # print('%s is running'%name,current_process().pid) 8 print('%s is running'%name,'子进程%s'%os.getpid(),'父进程%s'%os.getppid()) 9 time.sleep(3) 10 print('%s is over'%name) 11 12 13 if __name__ == '__main__': 14 p = Process(target=test,args=('egon',)) 15 p.start() 16 p.terminate() # 杀死当前进程 其实是告诉操作系统帮你杀死一个进程 17 time.sleep(0.1) 18 print(p.is_alive()) # 判断进程是否存活 19 # print('主',current_process().pid) 20 print('主', os.getpid(), '主主进程:%s'%os.getppid())
属性:
1 p.daemon:默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,p不能创建自己的子进程,必须在p.start()之前设置
2 p.name:进程的名称
3 p.pid:进程的pid
4 查看进程的pid os.getpid()

1 from multiprocessing import Process 2 import time 3 4 5 def test(name): 6 print('%s总管正常活着'%name) 7 time.sleep(3) 8 print('%s总管正常死亡'%name) 9 10 11 if __name__ == '__main__': 12 p = Process(target=test,args=('egon',)) 13 p.daemon = True # 将该进程设置为守护进程 这一句话必须放在start语句之前 否则报错 14 p.start() 15 time.sleep(0.1) 16 print('皇帝jason寿正终寝')
互斥锁:#

1 from multiprocessing import Process,Lock 2 import time 3 import json 4 5 # 查票 6 def search(i): 7 with open('data','r',encoding='utf-8') as f: 8 data = f.read() 9 t_d = json.loads(data) 10 print('用户%s查询余票为:%s'%(i,t_d.get('ticket'))) 11 12 # 买票 13 def buy(i): 14 with open('data','r',encoding='utf-8') as f: 15 data = f.read() 16 t_d = json.loads(data) 17 time.sleep(1) 18 if t_d.get('ticket') > 0: 19 # 票数减一 20 t_d['ticket'] -= 1 21 # 更新票数 22 with open('data','w',encoding='utf-8') as f: 23 json.dump(t_d,f) 24 print('用户%s抢票成功'%i) 25 else: 26 print('没票了') 27 28 29 def run(i,mutex): 30 search(i) 31 mutex.acquire() # 抢锁 只要有人抢到了锁 其他人必须等待该人释放锁 32 buy(i) 33 mutex.release() # 释放锁 34 35 36 if __name__ == '__main__': 37 mutex = Lock() # 生成了一把锁 38 for i in range(10): 39 p = Process(target=run,args=(i,mutex)) 40 p.start()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)