1. 程式人生 > >Python學習的第36天程序之守護程序、互斥鎖

Python學習的第36天程序之守護程序、互斥鎖

一、守護程序:

1、守護程序: 本質就是一個"子程序",該"子程序"的生命週期<=被守護程序的生命週期,當一個程序作為守護程序時 被被守護的程序死亡時 守護程序也跟隨死亡

2、使用

from multiprocessing import Process
import time

def task(name):
    print('老太監%s活著....' %name)
    time.sleep(3)
    print('老太監%s正常死亡....' %name)

if __name__ == '__main__':
    p=Process(target=task,args=('
劉清政',)) p.daemon=True #一定要在p.start()前設定, 設定p為守護程序, 禁止p建立子程序, 並且父程序程式碼執行結束, p即終止執行
 p.start() time.sleep(1) print('皇上:EGON正在死...')    # 只要終端打印出這一行內容, 那麼守護程序p也就跟著結束掉了

二、互斥鎖

1、為什麼要用互斥鎖:

在記憶體中程序之間是被物理隔開的,程序之間資料不共享,要是想共享資料只能從它們公有的資源硬碟(檔案)的讀寫來實行,但是有個問題:雖然程序們可以一起讀取檔案,但是當一起寫檔案的時候會出現資源的競爭,都會搶著去寫檔案,競爭帶來的結果是錯亂,如下:多個程序模擬多個人執行搶票任務

 db.json檔案內容:
{"count": 1}

import json, time, random
from multiprocessing import Process

def search(name):
    with open("db.json", "rt", encoding="utf-8") as f:
        dic = json.load(f)
    time.sleep(1)   # 模擬檢視票數的網路延遲
    print("%s檢視到餘票為%s張" %(name, dic["count"]))

def get(name):
    with open(
"db.json", "rt", encoding="utf-8") as f: dic = json.load(f) if dic["count"] > 0: dic["count"] -= 1 time.sleep(random.randint(1, 3)) # 模擬買票的網路延遲 with open("db.json", "wt", encoding="utf-8") as f: json.dump(dic, f) print("%s購票成功" %name) else: print("%s檢視到沒有票了" %name) def task(name): search(name) get(name) if __name__ == '__main__': for i in range(10): p = Process(target=task, args=("路人%s " %i,)) p.start() # 執行結果 路人0 檢視到餘票為1張 路人1 檢視到餘票為1張 路人2 檢視到餘票為1張 路人3 檢視到餘票為1張 路人4 檢視到餘票為1張 路人5 檢視到餘票為1張 路人6 檢視到餘票為1張 路人7 檢視到餘票為1張 路人9 檢視到餘票為1張 路人8 檢視到餘票為1張 路人0 購票成功 路人3 購票成功 路人4 購票成功 路人7 購票成功 路人9 購票成功 路人1 購票成功 路人2 購票成功 路人6 購票成功 路人8 購票成功 路人5 購票成功

可以看到,它們10個人是併發執行,效率高,但競爭寫同一檔案,資料寫入錯亂,只有一張票,卻成功賣給了10個人。之前學到 join,但 join 的操作相當於指定了買票的順序,只能由第一個人買,並不能保證資料的安全性。

所以要進行加鎖處理。而互斥鎖的意思就是互相排斥,如果把多個程序比喻為多個人,互斥鎖的工作原理就是多個人都要去爭搶同一個資源:衛生間,一個人搶到衛生間後上一把鎖,其他人都要等著,等到這個完成任務後釋放鎖,其他人才有可能有一個搶到......所以互斥鎖的原理,就是把部分的併發改成序列,降低了效率,但保證了資料安全不錯亂

import json, time, random
from multiprocessing import Process, Lock

def search(name):
    with open("db.json", "rt", encoding="utf-8") as f:
        dic = json.load(f)
    time.sleep(1)   # 模擬檢視票數的網路延遲
    print("%s檢視到餘票為%s張" %(name, dic["count"]))

def get(name):
    with open("db.json", "rt", encoding="utf-8") as f:
        dic = json.load(f)
    if dic["count"] > 0:
        dic["count"] -= 1
        time.sleep(random.randint(1, 3))    # 模擬買票的網路延遲

        with open("db.json", "wt", encoding="utf-8") as f:
            json.dump(dic, f)
            print("%s 購票成功" %name)
    else:
        print("%s 檢視到沒有票了" %name)

def task(name, mutex):
    search(name)    # 併發
    mutex.acquire()     # 加鎖
    get(name)       # 序列
    mutex.release()     # 釋放鎖

    # with mutex:   # 相當於mutex.acquire(),執行完子程式碼塊自動執行mutex.release()
    #     get(name)

if __name__ == '__main__':
    mutex = Lock()
    for i in range(10):
        p = Process(target=task, args=("路人%s " %i, mutex))
        p.start()

# 執行結果
路人0 檢視到餘票為1張
路人1 檢視到餘票為1張
路人3 檢視到餘票為1張
路人2 檢視到餘票為1張
路人4 檢視到餘票為1張
路人5 檢視到餘票為1張
路人6 檢視到餘票為1張
路人7 檢視到餘票為1張
路人8 檢視到餘票為1張
路人9 檢視到餘票為1張
路人0  購票成功
路人1  檢視到沒有票了
路人3  檢視到沒有票了
路人2  檢視到沒有票了
路人4  檢視到沒有票了
路人5  檢視到沒有票了
路人6  檢視到沒有票了
路人7  檢視到沒有票了
路人8  檢視到沒有票了
路人9  檢視到沒有票了