1. 程式人生 > 實用技巧 >程序互斥鎖

程序互斥鎖

程序互斥鎖

程序之間資料不共享,但是共享同一套檔案系統(如硬碟、鍵盤、cpu等),所以訪問同一個檔案,或同一個列印終端,是沒有問題的,競爭帶來的結果就是錯亂,如何控制,就是加鎖處理,即程序加鎖。

#併發執行,效率高,但競爭同一列印終端,帶來了列印錯亂
from multiprocessing import Process
import os,time
def work():
    print('%s is running' %os.getpid())
    time.sleep(2)
    print('%s is done' %os.getpid())

if __name__ == '
__main__': for i in range(3): p=Process(target=work) p.start() # 併發執行,效率高,但競爭同一列印終端,帶來了列印錯亂

特點:

  1.某程序先獲取到cpu資源之後,要立即上鎖,避免其他人對資源的競爭,只有當該程序解鎖(釋放)之後,剩餘的程序才能進行競爭。

  2.程序互斥鎖使得程式的執行順序成為序列,犧牲了效率,但提高了安全性。

  3.同一時刻只允許一個程序執行,其他程序只能等待。(這與後面的訊號量相反,訊號量允許多個程序同時執行)

程式碼示例:

1 from multiprocessing import
Process,Lock 2 import os,time 3 def work(lock): 4 lock.acquire() #上鎖 5 print('%s is running' %os.getpid()) 6 time.sleep(2) 7 print('%s is done' %os.getpid()) 8 lock.release()#解鎖 9 if __name__ == '__main__': 10 lock = Lock()#建立一個互斥鎖物件 11 for i in range(3): 12 p=Process(target=work,args=(lock,))
13 p.start() 程序互斥鎖

互斥鎖解決搶票問題:

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

def search():
    with open('db.txt',encoding='utf-8') as f:#在當前目錄建立一個db.txt檔案,並寫入“ {"count":1} ”
        dic=json.load(f)
        print('%s 剩餘票數 %s' %(os.getpid(),dic['count']))

def get():
    with open('db.txt',encoding='utf-8') as read_f:
        dic=json.load(read_f)

    if dic['count'] > 0:
        dic['count']-=1
        time.sleep(random.randint(1,3)) #模擬手速+網速
        with open('db.txt','w',encoding='utf-8') as write_f:
            json.dump(dic,write_f)
            print('%s 搶票成功' %os.getpid())

def task(mutex):
    search()
    mutex.acquire()
    get()
    mutex.release()

if __name__ == '__main__':
    mutex=Lock()
    for i in range(20):
        p=Process(target=task,args=(mutex,))
        p.start()
        p.join()

總結:

  加鎖可以保證多個程序修改同一塊資料,但是同一時刻只允許一個程序對其修改,其他程序必須等待,即穿行修改,犧牲了效率,但保證了資料的安全性,但如果加鎖的步驟增多,又會造成程式的複雜性。

擴充套件:

  因此我們最好找尋一種解決方案能夠兼顧:1、效率高(多個程序共享一塊記憶體的資料)2、幫我們處理好鎖問題。這就是mutiprocessing模組為我們提供的基於訊息的IPC通訊機制:佇列和管道。佇列和管道都是將資料存放於記憶體中佇列又是基於(管道+鎖)實現的,可以讓我們從複雜的鎖問題中解脫出來,我們應該儘量避免使用共享資料,儘可能使用訊息傳遞和佇列,避免處理複雜的同步和鎖問題,而且在程序數目增多時,往往可以獲得更好的可獲展性。