第三十六天 守護程序 互斥鎖 程序間通訊
一.昨日回顧
1. 程序 相關概念
併發 看起來像是同時執行的中 本質是不停切換執行 多個程序隨機執行
並行 同一時刻 多個程序 同時進行 只有多喝處理器才有真正的並行
序列 一個一個 依次排隊執行
阻塞 遇到了I/O操作 看起來就是程式碼卡住了
非阻塞 不會卡住程式碼的執行
阻塞 和 非阻塞 說的是同一個程序的情況下
同步 一個呼叫必須獲得返回結果才能繼續執行
非同步 一個呼叫發起後 發起反不需要等待他的返回值
同步和非同步 必須存在多個程序(執行緒)
無論是程序還是執行緒都是兩條獨立執行的路徑
2.如何使用多程序
P= Process(taget=一個函式,args=(函式的引數))
p.start()讓作業系統啟動這個程序
3.多程序的執行順序
主程序必須先執行
子程序應該在主程序後執行
一旦子程序啟動了 後續的順序就無法控制了
二.今日內容
1.守護程序
守護 就是看著 陪著
在程式碼中 程序只能由程序類守護
一個程序守護著另一個程序 指的是兩個程序之間的關聯關係
特點:守護程序(妃子)在守護程序(皇帝)死亡時 會跟隨被守護程序死亡
守護程序能不能先死?
2.互斥鎖
3.IPC
4.生產者消費者模型
三.守護程序
from multiprocessing import Process
impot time
def task():
print("福晉 升級為皇后")
time.sleep(3)
print("皇后陪葬")
if __name__=='__main__':
p = Process(targe=task)
# 將這個子程序設定為當前程序守護程序
p.daemon
p.start()
p.start()
print("崇禎登基")
print("崇禎駕崩了")
# 守護者程序的程式碼非常簡單
p.daemon = True
注意必須在啟動程序之前執行
什麼時候需要使用守護程序
例如:qq中有個下載視訊 應該用子程序去做 但是 下載的過程種 qq退出 那麼下載也沒必要繼續了
使用場景不多 瞭解即可
四.互斥鎖
from multiprocessing import Process,Lock #程序間 記憶體空間是相互獨立的 def task(lock): lock.acquire() for i in range(1000): print("===") lock.release() def task2(lock): lock.acquire() for I in range(1000): print("=====") def task3(lock): lock.acquire() for i in rang(1000): print("=====") lock.release() if __name__='__main__': mute = Lock() p1 = Process(target=task1,args=(mutex,)) p2 = Process(target=task2,args=(mutex,)) p3 = Process(target=task3,args=(mutex,)) p1.start() p2.start() p3.start() print("over!")
搶票系統
搶票---多個使用者在同時讀寫一個數據
from multiprocessing import Process,Lock import json,time,random def show_ticket(name): time.sleep(random.randint(1,3)) with open(r"ticket.json","rt",encoding="utf-8")as f: dic = json.load(f) print("%s檢視 剩餘票數:%s"%(name,dic["count"])) # 購買票 def buy_ticket(name): with open(r"ticket.json","rt",encoding="utf-8")as f: #修改資料 dic = json.load(f) if dic["count"] > 0: time.sleep(random.randint(1,3)) with open(r"ticket.json","wt",encoding="utf-8")as f2: json.dump(dic,f2) print("%s 購票成功!"%name) def task(lock,name): show_ticket(name) lock.acquire() buy_ticket(name) lock.release() if __name__=='__main__': mutex =Lock() for i in range(11): p = Process(target=task,args=(mutex,"客戶%s"%i)) p.start()
五.程序間通訊
IPC 指的是程序間通訊
之所以開啟紫金財產 肯定需要他幫我們完成任務 很多情況下 需要將資料返回給父程序
然而,程序記憶體是物理隔離的
解決方案:
1.將共享資料放到檔案中 就是慢
2.管道 subprocess中那個 管道只能單向通訊 必須存在父子關係
3.共享一塊記憶體區域 得作業系統幫你分配 速度快
from multiprocessing import Process,Manager import time def task(dic): print("子程序xxxxxx") dic["name"] = "xx" if __name__'__main__': m =Manager() dic = m.dict({}) p = Process(target=task,args=(dic,)) p.start() time.sleep(3) print(dic)
程序間通訊的另一種方式 使用 queue
queue 佇列
佇列的特點:
先進先出
後進後出
就像扶梯
from multiprocessing import Process,Queue # 阻塞操作 必須掌握 q = Queue(3) # # 存入資料 q.put("hello",block=False) q.put(["1","2","3"],block=False) q.put(1,block=False) # 當容量滿的時候 再執行put 預設會阻塞直到執行力了get為止 # 如果修改block=False 直接報錯 因為沒地方放了 # q.put({},block=False) # # # 取出資料 print(q.get(block=False)) print(q.get(block=False)) print(q.get(block=False)) # 對於get 當佇列中中沒有資料時預設是阻塞的 直達執行了put # 如果修改block=False 直接報錯 因為沒資料可取了 print(q.get(block=False))