1. 程式人生 > >守護程序 互斥鎖 程序間通訊

守護程序 互斥鎖 程序間通訊

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)