9-2 事件,信號量,隊列,鎖

一 鎖(Lock)json

當多個進程使用同一份數據資源的時候,就會引起數據安全或順序混亂問題。就會用到鎖安全

例如:買火車票,我如今只有一張票,10我的來買,若是不加鎖,就會顯示10我的都買到網絡

 1 from multiprocessing import Process,Lock
 2 import time,json,random
 3 def search():#查票
 4     dic=json.load(open('db'))
 5     print('\033[31m剩餘票數%s\033[0m' %dic['count'])
 6 
 7 def get(num):#買票
 8     dic=json.load(open('db'))
 9     time.sleep(random.random()) #模擬讀數據的網絡延遲
10     if dic['count'] >0:
11         dic['count']-=1
12         time.sleep(random.random()) #模擬寫數據的網絡延遲
13         json.dump(dic,open('db','w'))
14         print('\033[31m用戶%s購票成功\033[0m'%num)
15 
16 def task(num,lock):
17     search()
18     lock.acquire()
19     get(num)
20     lock.release()
21 
22 if __name__ == '__main__':
23     lock = Lock()
24     for i in range(10): #模擬併發10個客戶端搶票
25         p=Process(target=task,args = (i,lock))
26         p.start()

還有我開啓三個進程讓一一對應啓動和結束一樣也用到了鎖併發

 1 import os
 2 import time
 3 import random
 4 from multiprocessing import Process,Lock
 5 
 6 def work(n,lock):
 7     lock.acquire()#取的鑰匙
 8     print('%s:%s is running'%(n,os.getpid()))
 9     time.sleep(random.random())
10     print('%s:%s is done' %(n,os.getpid()))
11     lock.release()#釋放
12 if __name__ == '__main__':
13     lock=Lock()
14     for i in range(3):
15         p=Process(target=work,args=(i,lock))
16         p.start()
17 
18 結果:
19 0:25068 is running
20 0:25068 is done
21 1:24296 is running
22 1:24296 is done
23 2:24092 is running
24 2:24092 is done

二 事件(Event)(用的不多)app

# 事件內部內置了一個標誌
# wait 方法 若是這個標誌是True,那麼wait == pass
# wait 方法 若是這個標誌是False,那麼wait就會陷入阻塞,一直阻塞到標誌從False變成True

# 一個事件在建立之初 內部的標誌默認是False
# Flase -> True set()
# True -> False clear()
例子:紅路燈模型
說明:
# 10個進程 模擬車 :車的行走要依靠當時的交通燈
# 交通燈是綠燈 車就走
# 交通燈是紅燈 車就停 停到燈變綠
# wait 來等燈
# set clear 來控制燈
 1 from multiprocessing import Process, Event
 2 import time, random
 3 
 4 def car(e, n):
 5     while True:
 6         if not e.is_set():
 7             # 進程剛開啓,is_set()的值是Flase,模擬信號燈爲紅色
 8             print('\033[31m紅燈亮\033[0m,car%s等着' % n)
 9             e.wait()    # 阻塞,等待is_set()的值變成True,模擬信號燈爲綠色
10             print('\033[32m車%s 看見綠燈亮了\033[0m' % n)
11             time.sleep(random.randint(3, 6))
12             if not e.is_set():   #若是is_set()的值是Flase,也就是紅燈,仍然回到while語句開始
13                 continue
14             print('車開遠了,car', n)
15             break
16 
17 def traffic_lights(e, inverval):
18     while True:
19         time.sleep(inverval)   # 先睡3秒
20         if e.is_set():         # 標誌是True
21             print('######', e.is_set())
22             e.clear()  # ---->將is_set()的值設置爲False
23         else:                 # 標誌是False
24             e.set()    # ---->將is_set()的值設置爲True
25             print('***********',e.is_set())
26 
27 
28 if __name__ == '__main__':
29     e = Event()   #e就是事件
30     t = Process(target=traffic_lights, args=(e, 3))  # 建立一個進程控制紅綠燈
31     for i in range(10):
32         p=Process(target=car,args=(e,i,))  # 建立10個進程控制10輛車
33         p.start()
34     t.start()
35 
36     print('============》')

三 隊列 (Queue)dom

q.get( [ block [ ,timeout ] ] ) 
返回q中的一個項目。若是q爲空,此方法將阻塞,直到隊列中有項目可用爲止。block用於控制阻塞行爲,默認爲True. 若是設置爲False,將引起Queue.Empty異常(定義在Queue模塊中)。timeout是可選超時時間,用在阻塞模式中。若是在制定的時間間隔內沒有項目變爲可用,將引起Queue.Empty異常。

q.get_nowait( ) 
同q.get(False)方法。

q.put(item [, block [,timeout ] ] ) 
將item放入隊列。若是隊列已滿,此方法將阻塞至有空間可用爲止。block控制阻塞行爲,默認爲True。若是設置爲False,將引起Queue.Empty異常(定義在Queue庫模塊中)。timeout指定在阻塞模式中等待可用空間的時間長短。超時後將引起Queue.Full異常。

 

建立共享的進程隊列,Queue是多進程安全的隊列,能夠使用Queue實現多進程之間的數據傳遞。 ui

例子:spa

 1 from multiprocessing import Queue,Process
 2 
 3 def func(q,num):
 4     try:
 5         t = q.get_nowait() #拿一張票 不阻塞直接報錯同q.get(False)
  6 print("%s搶到票了"%num)  7 except:pass  8  9 if __name__ == '__main__': 10 q = Queue() 11 q.put(1) #往裏面放一張票 12 for i in range(10):#建立了10我的去搶一張票 13 Process(target=func,args=(q,i)).start() 14 15 16 #結果是隻有一我的買到了票

 

四信號量  (Semaphore)瞭解便可,不多用線程

如:code

互斥鎖同時只容許一個線程更改數據,而信號量Semaphore是同時容許必定數量的線程更改數據 。
假設商場裏有4個迷你唱吧,因此同時能夠進去4我的,若是來了第五我的就要在外面等待,等到有人出來才能再進去玩

 1 from multiprocessing import Process,Semaphore
 2 import time,random
 3 def go_ktv(sem,user):
 4     sem.acquire()
 5     print('%s佔到一件ktv小屋' %user)
 6     time.sleep(random.randint(3,5))
 7     sem.release()
 8     print('%s走出小屋'%user)
 9 if __name__ == '__main__':
10     sem=Semaphore(4)
11     p_l=[]
12     for i in range(13):
13         p=Process(target=go_ktv,args=(sem,'user%s' %i,))
14         p.start()
15         p_l.append(p)
16     for i in p_l:
17         i.join()
18     print('##########')
相關文章
相關標籤/搜索