鎖,信號量 ,事件 Event模塊
阿新 • • 發佈:2018-08-21
搶票 time 等待 數量 出現 money nbsp %s tick
1. 鎖
Lock模塊: 保證一段代碼,在同一時刻只能被一個進程執行.
lock = Lock() 創造了一把鎖
acquire() 獲取鎖的鑰匙
release() 歸還這把鎖的鑰匙
ps: 多進程的數據的不安全性: 當多個進程共享一段數據的時候, 數據會出現不安全的現象, 需要加鎖, 來維護數據的安全性.
例:
搶票:
搶票分析: 客戶可以同一時間訪問服務器,並且訪問到 同一個余票數 當客戶發出購買請求, 服務器必須進行同步處理, 一個一個來. from multiprocessing import Process,Lock import time def check(i): with open(‘余票‘) as f: con = f.read() print(‘第%s個人查到余票還剩%s張‘%(i,con)) def buy_ticket(i,l): l.acquire()# 拿鑰匙,鎖門 with open(‘余票‘) as f: con = int(f.read()) time.sleep(0.1) if con > 0: print(‘\033[31m 第%s個人買到票了\033[0m‘%i) con -= 1 else: print(‘\033[32m 第%s個人沒有買到票\033[0m‘%i) time.sleep(0.1)# 是指 買完票後,把余票數量重寫寫入數據庫的時間延遲 with open(‘余票‘,‘w‘) as f: f.write(str(con)) l.release()# 還鑰匙,開門 if __name__ == ‘__main__‘: l = Lock() for i in range(10): p_ch = Process(target=check,args=(i+1,)) p_ch.start() for i in range(10): p_buy = Process(target=buy_ticket,args=(i+1,l)) p_buy.start()
銀行同時取錢.存錢:
from multiprocessing import Process,Value,Lock import time def get_money(num,l):# 取錢 l.acquire()# 拿走鑰匙,鎖上門,不允許其他人進屋 for i in range(100): num.value -= 1 print(num.value) time.sleep(0.01) l.release()# 還鑰匙,打開門,允許其他人進屋 def put_money(num,l):# 存錢 l.acquire() for i in range(100): num.value += 1 print(num.value) time.sleep(0.01) l.release() if __name__ == ‘__main__‘: num = Value(‘i‘,100) l = Lock() p = Process(target=get_money,args=(num,l)) p.start() p1 = Process(target=put_money, args=(num,l)) p1.start() p.join() p1.join() print(num.value)
2, 信號量
Semaphore模塊: 多把鑰匙 對應一把鎖
本質就是: lock+count 計數 來實現的
sem = Semaphore(n)
n : 是指初始化一把鎖配幾把鑰匙,一個int型
拿鑰匙,鎖門 l.acquire()
還鑰匙,開門 l.release()
信號量機制比鎖機制多了一個計數器,這個計數器是用來記錄當前剩余幾把鑰匙的。
當計數器為0時,表示沒有鑰匙了,此時acquire()處於阻塞。
對於計數器來說,每acquire一次,計數器內部就減1,release一次,計數器就加1
例:
發廊:
from multiprocessing import Process,Semaphore import time import random def func(i,sem): sem.acquire() print(‘\033[31m 第%s個人進入小黑屋,拿了鑰匙鎖上門\033[0m‘ % i) time.sleep(random.randint(3,5)) print(‘\033[32m 第%s個人出去小黑屋,還了鑰匙打開門 \033[0m‘ % i) sem.release() if __name__ == ‘__main__‘: sem=Semaphore(5)# 初始化了一把鎖5把鑰匙,也就是說允許5個人同時進入小黑屋 # 之後其他人必須等待,等有人從小黑屋出來,還了鑰匙,才能允許後邊的人進入 for i in range(20): p=Process(target=func,args=(i,sem,)) p.start()
3, 事件 Event模塊:
標誌:在 事件創立之初,標誌默認為False
wait(timeout=None) 等待 有一個關鍵字參數 timeout(超時) 以秒為單位.
e = Event()
# e.set() #將is_set()設為True
# e.clear() # 將is_set()設為False
# e.wait() #判斷is_set的bool值,如果bool為True,則非阻塞,bool值為False,則阻塞
# e.is_set() # 標識
# 事件是通過is_set()的bool值,去標識e.wait() 的阻塞狀態
# 當is_set()的bool值為False時,e.wait()是阻塞狀態
# 當is_set()的bool值為True時,e.wait()是非阻塞狀態
# 當使用set()時,是把is_set的bool變為True
# 當使用clear()時,是把is_set的bool變為False
例:
信號燈:
from multiprocessing import Process,Event import time import random def tra(e): ‘‘‘信號燈函數‘‘‘ # e.set() # print(‘\033[32m 綠燈亮! \033[0m‘) while 1:# 紅綠燈得一直亮著,要麽是紅燈要麽是綠燈 if e.is_set():# True,代表綠燈亮,那麽此時代表可以過車 time.sleep(5)# 所以在這讓燈等5秒鐘,這段時間讓車過 print(‘\033[31m 紅燈亮! \033[0m‘)# 綠燈亮了5秒後應該提示到紅燈亮 e.clear()# 把is_set設置為False else: time.sleep(5)# 此時代表紅燈亮了,此時應該紅燈亮5秒,在此等5秒 print(‘\033[32m 綠燈亮! \033[0m‘)# 紅的亮夠5秒後,該綠燈亮了 e.set()# 將is_set設置為True def Car(i,e): e.wait()# 車等在紅綠燈,此時要看是紅燈還是綠燈,如果is_set為True就是綠燈,此時可以過車 print(‘第%s輛車過去了‘%i) if __name__ == ‘__main__‘: e = Event() triff_light = Process(target=tra,args=(e,))# 信號燈的進程 triff_light.start() for i in range(50):# 描述50輛車的進程 if i % 3 == 0: time.sleep(2) car = Process(target=Car,args=(i+1,e,)) car.start()
鎖,信號量 ,事件 Event模塊