1. 守护进程:
from multiprocessing import Process
import time
def task():
print("11111111111111")
time.sleep(3)
print("222222222222")
if __name__ == '__main__':
p=Process(target=task)
p.daemon=True#p是主进程的守护进程
p.start()
print("3333333333")
print("4444444444")
#守护进程在被守护进程死亡时会随之死亡
#注意:p.daemon=True必须在启动进程前执行
2.互斥锁*****
当多个进程 同时读写同一份数据 数据很可能就被搞坏了。并发式读写会导致文件最后无法解码.(并发无法控制进程顺序)
目前可以使用join来将所有程序并发改成串行
多个进程并发的访问了同一个资源 将导致资源竞争(同时读取不会产生问题 同时修改才会出现问题)
第一个方案 加上join 但是这样就导致了不公平 相当于火车进站无论什么时间开的都必须按照队伍来,不能紧急通行
第二个方案 加锁 谁先抢到资源谁先处理
相同点:都编程了串行
不同点:join顺序是固定的 加锁的顺序不是固定的
注意:要想锁住资源必须保证大家拿到的是同一把锁
怎么使用?
在需要加锁的地方 lock.acquire()表示锁定 ,在代码执行完后 一定要lock.release()
加锁举例:
from multiprocessing import Process,Lock
import time
#买了把锁
mutex = Lock()
def task1(Lock):
Lock.acquire()
time.sleep(3)
print("===>")
Lock.release()
def task2(Lock):
Lock.acquire()
print("=======>")
Lock.release()
def task3(Lock):
Lock.acquire()
print("===============>")
Lock.release()
if __name__ == '__main__':
p1 = Process(target=task1,args=(mutex,))
p2 = Process(target=task2,args=(mutex,))
p3 = Process(target=task3,args=(mutex,))
p1.start()
p3.start()
p2.start()
print("over")
#加锁后开启进程顺序就变成了 执行进程顺序(串性)
例子:抢票
from multiprocessing import Process,Lock
import json
import time,random
#买了把锁
def task1(name):
time.sleep(random.randint(1,3))
with open("D:py_yingyong新课上练习ppppp.json","rt",encoding="utf-8")as f:
dic=json.load(f)
print("%s进行了查票 余票%s张"%(name,dic["count"]))
return dic
def task2(name):
time.sleep(random.randint(1,3))
with open("D:py_yingyong新课上练习ppppp.json","rt",encoding="utf-8")as f:
dic=json.load(f)
print("%s进行了购票操作 现余票%s张"%(name,dic["count"]))
if dic["count"]>0:
dic["count"]=dic["count"] - 1
with open("D:py_yingyong新课上练习ppppp.json", "wt", encoding="utf-8")as f:
json.dump(dic,f)
print("%s购票成功"%name)
return
def task3(Lock,name):
task1(name)
Lock.acquire()
task2(name)
Lock.release()
if __name__ == '__main__':
mutex = Lock()
for i in range(5):
p1 = Process(target=task3,args=(mutex,"客户%s"%i))
p1.start()
3.IPC
指的是进程间的通讯
之所以开启子进程 肯定是需要他来帮我们完成任务 很多情况下,需要将数据返回给父进程
然而 进程内存是物理隔离的
解决方案:
1.将共享数据放到文件中
2.管道 subprocess中的那个 管道只能单项通讯 必须存在父子关系
3.共享一个内存区域 需要操作系统帮你分配 速度快:
Manager 共享列表或字典
from multiprocessing import Process, Manager
import time
def task(li,i):
print("子进程xxxx")
li[0]=1+i
print(li[0])
# dic["name"]="xx"
if __name__ == '__main__':
# with Manager() as m:
m=Manager()
li=m.list([2])
# dic=m.dict({})
# li=[1]
#开启子进程
for i in range(3):
p=Process(target=task,args=(li,i))
p.start()
p.join(1)
print(li)
Queue 是一个队列 带有阻塞效果:
from multiprocessing import Process,Queue
#创建队列
q=Queue()#阻塞
q.put("len")
q.put(124)
q.put("kkkk")
print(q.get())
#如果取空会等待
print(q.get())
q=Queue(3)#阻塞 先进先出
q.put("len",block=False)
#当容量满的时候在执行put会默认阻塞知道执行了get为止
#如果修改block=False 直接报错 因为没有地方放了
q.put(124,block=False)
q.put("kkkk",block=False)
#去除数据 如果没有数据默认是阻塞的 直到执行了put
#如果取空会等待
print(q.get(),block=False)
#如果修改block=False 直接报错 因为没有数据可以取了
print(q.get(),block=False)
print(q.get())
print(q.get())
q=Queue()
#如果满了 愿意等待3秒 如果还等不到位置 就会报错
q.put("len",timeout=3)
q.put(124,timeout=3)
q.put("kkkk",timeout=3)
print(q.get(),timeout=3)
#如果数据空了 愿意等待3秒 如果还没有数据 就会报错
print(q.get(),timeout=3)
print(q.get(),timeout=3)
print(q.get(),timeout=3)