1. 程式人生 > >第三十六天 守護程序 互斥鎖 程序間通訊

第三十六天 守護程序 互斥鎖 程序間通訊

一.昨日回顧

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))