提前設定好,一個房間只有4個床(計數器現在為4),那么同時只能四個人進來,誰先來的誰先占一個床(acquire,計數器減1),4個床滿了之后(計數器為0了),第五個人就要等着,等其中一個人出來(release,計數器加1),他就去占用那個床了。
互斥鎖同時只允許一個線程更改數據,而信號量Semaphore是同時允許一定數量的線程更改數據 。 假設商場里有4個迷你唱吧,所以同時可以進去4個人,如果來了第五個人就要在外面等待,等到有人出來才能再進去玩。 實現: 信號量同步基於內部計數器,每調用一次acquire(),計數器減1;每調用一次release(),計數器加1.當計數器為0時,acquire()調用被阻塞。這是迪科斯徹(Dijkstra)信號量概念P()和V()的Python實現。信號量同步機制適用於訪問像服務器這樣的有限資源。 信號量與進程池的概念很像,但是要區分開,信號量涉及到加鎖的概念
# -*- coding: utf-8 -*- import os import time from multiprocessing import Process def go_ktv(i): print("user%s正在....ktv.子進程(%s)" % (i, os.getpid())) time.sleep(2) if __name__ == '__main__': '''開啟20個進程,操作系統可以調度4個cpu去執行,進程的調用比線程的開銷大些''' start_time = time.time() p_lst = [] for i in range(20): p = Process(target=go_ktv, args=(i,)) p.start() p_lst.append(p) [pp.join() for pp in p_lst] print("運行時間: %s.主進程<%s>" % ((time.time() - start_time), os.getpid())) # user0正在....ktv.子進程(5496) # user1正在....ktv.子進程(6996) # user3正在....ktv.子進程(6328) # user2正在....ktv.子進程(1064) # user4正在....ktv.子進程(4844) # user7正在....ktv.子進程(7804) # user5正在....ktv.子進程(7688) # user8正在....ktv.子進程(7136) # user6正在....ktv.子進程(7824) # user9正在....ktv.子進程(7812) # user10正在....ktv.子進程(8148) # user11正在....ktv.子進程(2556) # user13正在....ktv.子進程(4744) # user15正在....ktv.子進程(6232) # user14正在....ktv.子進程(5168) # user16正在....ktv.子進程(6444) # user12正在....ktv.子進程(2616) # user17正在....ktv.子進程(5188) # user18正在....ktv.子進程(8088) # user19正在....ktv.子進程(7224) # 運行時間: 3.2611865997314453.主進程<6936>
# -*- coding: utf-8 -*- import os import time from multiprocessing import Pool def go_ktv(i): print("user%s正在....ktv.子進程(%s)" % (i, os.getpid())) time.sleep(2) if __name__ == '__main__': '''創建進程池,進程的容量默認是4,
如果總進程的數量超過4,就會自動排隊等待,一次可執行4個進程,進程池內的進程結束一個,就會自動進來一個新的進程,重用原來的進程號,節省開銷''' start_time = time.time() pool = Pool() p_lst = [] for i in range(20): pool.apply_async(go_ktv, args=(i,)) pool.close() pool.join() print("運行時間: %s.主進程<%s>" % ((time.time() - start_time), os.getpid())) # user0正在....ktv.子進程(7396) # user1正在....ktv.子進程(1760) # user2正在....ktv.子進程(8000) # user3正在....ktv.子進程(4120) # user4正在....ktv.子進程(7396) # user5正在....ktv.子進程(1760) # user6正在....ktv.子進程(8000) # user7正在....ktv.子進程(4120) # user8正在....ktv.子進程(7396) # user9正在....ktv.子進程(1760) # user10正在....ktv.子進程(8000) # user11正在....ktv.子進程(4120) # user12正在....ktv.子進程(7396) # user13正在....ktv.子進程(1760) # user14正在....ktv.子進程(8000) # user15正在....ktv.子進程(4120) # user16正在....ktv.子進程(7396) # user17正在....ktv.子進程(1760) # user18正在....ktv.子進程(8000) # user19正在....ktv.子進程(4120) # 運行時間: 10.851620435714722.主進程<7428>
# -*- coding: utf-8 -*- import os import time from multiprocessing import Process, Semaphore def go_ktv(i, sem): with sem: print("user%s正在....ktv.子進程(%s)" % (i, os.getpid())) time.sleep(2) if __name__ == '__main__': '''開啟20個進程,一次可執行4(信號量容量)個進程,相當於添加另一個互斥鎖''' start_time = time.time() sem = Semaphore(4) p_lst = [] for i in range(20): p = Process(target=go_ktv, args=(i, sem)) p.start() p_lst.append(p) [pp.join() for pp in p_lst] print("運行時間: %s.主進程<%s>" % ((time.time() - start_time), os.getpid())) # user0正在....ktv.子進程(3660) # user1正在....ktv.子進程(7188) # user3正在....ktv.子進程(7268) # user2正在....ktv.子進程(7568) # user5正在....ktv.子進程(2896) # user6正在....ktv.子進程(2852) # user7正在....ktv.子進程(376) # user4正在....ktv.子進程(7532) # user9正在....ktv.子進程(8188) # user10正在....ktv.子進程(1444) # user12正在....ktv.子進程(6304) # user11正在....ktv.子進程(6776) # user14正在....ktv.子進程(6992) # user13正在....ktv.子進程(7248) # user8正在....ktv.子進程(6820) # user17正在....ktv.子進程(6308) # user15正在....ktv.子進程(8020) # user18正在....ktv.子進程(4312) # user16正在....ktv.子進程(2724) # user19正在....ktv.子進程(7516) # 運行時間: 10.443597078323364.主進程<2560>