Python 進程操作之同步控制--鎖
進程同步(multiprocess.Lock)
鎖 —— multiprocess.Lock
通過剛剛的學習,我們千方百計實現了程序的異步,讓多個任務可以同時在幾個進程中并發處理,他們之間的運行沒有順序,一旦開啟也不受我們控制。盡管并發編程讓我們能更加充分的利用IO資源,但是也給我們帶來了新的問題。
當多個進程使用同一份數據資源的時候,就會引發數據安全或順序混亂問題。
多進程搶占輸出資源:
import?os import?time import?random from?multiprocessing?import?Process def?work(n): ????print('%s:?%s?is?running'?%(n,os.getpid())) ????time.sleep(random.random()) ????print('%s:%s?is?done'?%(n,os.getpid())) if?__name__?==?'__main__': ????for?i?in?range(3): ????????p=Process(target=work,args=(i,)) ????????p.start()
使用鎖維護執行秩序:
#?由并發變成了串行,犧牲了運行效率,但避免了競爭 import?os import?time import?random from?multiprocessing?import?Process,Lock def?work(lock,n): ????lock.acquire() ????print('%s:?%s?is?running'?%?(n,?os.getpid())) ????time.sleep(random.random()) ????print('%s:?%s?is?done'?%?(n,?os.getpid())) ????lock.release() if?__name__?==?'__main__': ????lock=Lock() ????for?i?in?range(3): ????????p=Process(target=work,args=(lock,i)) ????????p.start()
上面這種情況雖然使用加鎖的形式實現了順序的執行,但是程序又重新變成串行了,這樣確實會浪費了時間,卻保證了數據的安全。
接下來,我們以模擬搶票為例,來看看數據安全的重要性。
多進程同時搶購余票:
#文件db的內容為:{"count":1} #注意一定要用雙引號,不然json無法識別 #并發運行,效率高,但競爭寫同一文件,數據寫入錯亂 from?multiprocessing?import?Process,Lock import?time,json,random def?search(): ????dic=json.load(open('db')) ????print('\033[43m剩余票數%s\033[0m'?%dic['count']) def?get(): ????dic=json.load(open('db')) ????time.sleep(0.1)?#模擬讀數據的網絡延遲 ????if?dic['count']?>0: ????????dic['count']-=1 ????????time.sleep(0.2)?#模擬寫數據的網絡延遲 ????????json.dump(dic,open('db','w')) ????????print('\033[43m購票成功\033[0m') def?task(): ????search() ????get() if?__name__?==?'__main__': ????for?i?in?range(100):?#模擬并發100個客戶端搶票 ????????p=Process(target=task) ????????p.start()
使用鎖來保證數據安全:
#文件db的內容為:{"count":5} #注意一定要用雙引號,不然json無法識別 #并發運行,效率高,但競爭寫同一文件,數據寫入錯亂 from?multiprocessing?import?Process,Lock import?time,json,random def?search(): ????dic=json.load(open('db')) ????print('\033[43m剩余票數%s\033[0m'?%dic['count']) def?get(): ????dic=json.load(open('db')) ????time.sleep(random.random())?#模擬讀數據的網絡延遲 ????if?dic['count']?>0: ????????dic['count']-=1 ????????time.sleep(random.random())?#模擬寫數據的網絡延遲 ????????json.dump(dic,open('db','w')) ????????print('\033[32m購票成功\033[0m') ????else: ????????print('\033[31m購票失敗\033[0m') def?task(lock): ????search() ????lock.acquire() ????get() ????lock.release() if?__name__?==?'__main__': ????lock?=?Lock() ????for?i?in?range(100):?#模擬并發100個客戶端搶票 ????????p=Process(target=task,args=(lock,)) ????????p.start()
#加鎖可以保證多個進程修改同一塊數據時,同一時間只能有一個任務可以進行修改,即串行的修改,沒錯,速度是慢了,但犧牲了速度卻保證了數據安全。 雖然可以用文件共享數據實現進程間通信,但問題是: 1.效率低(共享數據基于文件,而文件是硬盤上的數據) 2.需要自己加鎖處理 #因此我們最好找尋一種解決方案能夠兼顧:1、效率高(多個進程共享一塊內存的數據)2、幫我們處理好鎖問題。這就是mutiprocessing模塊為我們提供的基于消息的IPC通信機制:隊列和管道。 隊列和管道都是將數據存放于內存中 隊列又是基于(管道+鎖)實現的,可以讓我們從復雜的鎖問題中解脫出來, 我們應該盡量避免使用共享數據,盡可能使用消息傳遞和隊列,避免處理復雜的同步和鎖問題,而且在進程數目增多時,往往可以獲得更好的可獲展性。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。