1. 信號量 安全
對於多進程來講,多個進程同時修改數據,就可能出現安全隱患,因此引入了鎖,這一機制,但鎖只能有一把來控制一個的開關,當你須要幾把鎖的時候,就可能用到信號量的概念。他是用了鎖的原理,內置了一個計數器,在同一時內,只能有指定數量的進程來執行某一段被控制的代碼。dom
import time,random from multiprocessing import Process,Semaphore def singing(i,sem): ''' :param i: 隨機生成20個數的值 :param sem:生成的信號量 :return:None ''' sem.acquire()#得到鎖 print('%s is coming '%i) time.sleep(random.randint(10,20))#隨機在10秒至20秒中停頓 print('%s is going out'%i) sem.release()#釋放鎖 if __name__ == '__main__': sem = Semaphore(4)#生成4個鎖 for i in range(20): p = Process(target=singing,args=(i,sem)) p.start()
2. 事件函數
事件是經過一個信號來控制多個進程的同時執行或阻塞,當一個事件被建立的時候默認是阻塞狀態,但不影響進程的執行,當遇到 even.wait() 方法時,纔會阻塞。ui
# set 和 clear # 分別用來修改一個事件的狀態 True或者False # is_set 用來查看一個事件的狀態 # wait 是依據事件的狀態來決定本身是否在wait處阻塞 # False阻塞 True不阻塞
下面是一個紅綠燈的問題。spa
import time import random from multiprocessing import Event,Process def cars(e,i): ''' 一個判斷車是否經過的函數 :param e: 傳入一個事件 :param i: 生成的車幾 :return: None ''' if not e.is_set(): print('\033[0;31;40mcar %s 在等待~\033[0m'%i) e.wait() print('\033[32;40mcar %s 經過~\033[0m'%i) def light(e): ''' 控制紅綠燈的切換 :param e: 傳入事件 :return: None ''' while True: if e.is_set(): e.clear() print('\033[31m紅燈亮了\033[0m') time.sleep(3) else: e.set() print('\033[32m綠燈亮了\033[0m') time.sleep(5) if __name__ == '__main__': e = Event() traffic = Process(target=light,args=(e,)) traffic.start() time.sleep(1) for i in range(random.randint(5,10)): car = Process(target=cars,args=(e,i)) car.start() time.sleep(random.randint(1,3))
3. 隊列code
隊列 Queue 中只有少數幾個方法,blog
# put 當隊列滿的時候阻塞等待隊列有空位置 # get 當隊列空的時候阻塞等待隊列有數據 # full empty 不徹底準確
full 和 empty 不許一緣由在於,若是隊列回答主程序時,同時進程又對隊列進行了操做,這個就會形成數據的錯誤。隊列
4. 用 JoinableQueue 來處理生產者和消費者模型進程
import time import random from multiprocessing import Process,JoinableQueue def producer(name,food,q): for i in range(4): time.sleep(random.randint(1,3)) f = '%s生產了%s%s'%(name,food,i) print(f) q.put(f) q.join() # 阻塞 直到一個隊列中的全部數據 所有被處理完畢 def consumer(q,name): while True: food = q.get() print('\033[31m%s消費了%s\033[0m' % (name,food)) time.sleep(random.randint(1,3)) q.task_done() # count - 1 if __name__ == '__main__': q = JoinableQueue(20) p1 = Process(target=producer,args=('eli','dumpling',q)) p2 = Process(target=producer, args=('tom','noodle', q)) c1 = Process(target=consumer, args=(q,'mike')) c2 = Process(target=consumer, args=(q,'johan')) p1.start() p2.start() c1.daemon = True # 設置爲守護進程 主進程中的代碼執行完畢以後,子進程自動結束 c2.daemon = True c1.start() c2.start() p1.join() p2.join() # 感知一個進程的結束
以爲最好的點就是用到了守護進程(當主進程的程序執行完成時,子進程也隨之結束)。事件