37. Python 多進程鎖 多進程共享內存
阿新 • • 發佈:2017-12-11
python 多進程鎖 共享內存Lock組件
當我們用多進程來讀寫文件的時候,如果一個進程是寫文件,一個進程是讀文件,
如果兩個文件同時進行,肯定是不行的,必須是文件寫結束後,才可以進行讀操作。
或者是多個進程在共享一些資源的時候,同時只能有一個進程進行訪問,那就需要鎖機制進行控制。
需求:
一個進程寫入一個文件,一個進程追加文件,一個進程讀文件,同時啟動起來
我們可以通過進程的join()方法來實現,這是一種方法,本節用Lock(進程鎖)來實現。
函數說明:
# lock = multiprocessing.Lock()
# lock.acquire() ? ? ? ? ? ? ? ?#獲得鎖
# lock.release() ? ? ? ? ? ? ? ?#釋放鎖
先寫不加鎖的程序:
#不加鎖
# number ?+1
# number ?+3
import?multiprocessing import?time def?add(number,value,lock): ????print?("init?add{0}?number?=?{1}".format(value,?number)) ????for?i?in?xrange(1,?6): ????????number?+=?value ????????time.sleep(1) ????????print?("add{0}?number?=?{1}".format(value,?number)) ???????? if?__name__?==?"__main__": ????lock?=?multiprocessing.Lock() ????number?=?0 ????p1?=?multiprocessing.Process(target=add,args=(number,?1,?lock)) ????p2?=?multiprocessing.Process(target=add,args=(number,?3,?lock)) ????p1.start() ????p2.start() ????print?("main?end")
結果:
main?end init?add1?number?=?0 init?add3?number?=?0 add1?number?=?1 add3?number?=?3 add1?number?=?2 add3?number?=?6 add1?number?=?3 add3?number?=?9 add1?number?=?4 add3?number?=?12 add1?number?=?5 add3?number?=?15
再寫加鎖的程序:
import?multiprocessing import?time def?add(number,value,lock): ????with?lock: ????print?("init?add{0}?number?=?{1}".format(value,?number)) ????for?i?in?xrange(1,?6): ????????number?+=?value ????????time.sleep(1) ????????print?("add{0}?number?=?{1}".format(value,?number)) ???????? if?__name__?==?"__main__": ????lock?=?multiprocessing.Lock() ????number?=?0 ????p1?=?multiprocessing.Process(target=add,args=(number,?1,?lock)) ????p2?=?multiprocessing.Process(target=add,args=(number,?3,?lock)) ????p1.start() ????p2.start() ????print?("main?end")
結果:
main?end init?add1?number?=?0 #add1優先搶到鎖,優先執行 add1?number?=?1 add1?number?=?2 add1?number?=?3 add1?number?=?4 add1?number?=?5 init?add3?number?=?0 #add3被阻塞,等待add1執行完成,釋放鎖後執行add3 add3?number?=?3 add3?number?=?6 add3?number?=?9 add3?number?=?12 add3?number?=?15
使用 lock.acquire() 和 lock.release()
import?multiprocessing import?time def?add(number,value,lock): ????lock.acquire() ????try: ????????print?("init?add{0}?number?=?{1}".format(value,?number)) ????????for?i?in?xrange(1,?6): ????????????number?+=?value ????????????time.sleep(1) ????????????print?("add{0}?number?=?{1}".format(value,?number)) ????except?Exception?as?e: ????????raise?e ????finally: ????????lock.release() if?__name__?==?"__main__": ????lock?=?multiprocessing.Lock() ????number?=?0 ????p1?=?multiprocessing.Process(target=add,args=(number,?1,?lock)) ????p2?=?multiprocessing.Process(target=add,args=(number,?3,?lock)) ????p1.start() ????p2.start() ????print?("main?end")
結果:
main?end init?add1?number?=?0 add1?number?=?1 add1?number?=?2 add1?number?=?3 add1?number?=?4 add1?number?=?5 init?add3?number?=?0 add3?number?=?3 add3?number?=?6 add3?number?=?9 add3?number?=?12 add3?number?=?15
共享內存
python的multiprocessing模塊也給我們提供了共享內存的操作
一般的變量在進程之間是沒法進行通訊的,multiprocessing 給我們提供了 Value 和 Array 模塊,他們可以在不通的進程中共同使用
例子:不加鎖,讓number加完1後再繼續加3,再繼續加一,再繼續加3...
import?multiprocessing import?time def?add(number,add_value): ????try: ????????print?("init?add{0}?number?=?{1}".format(add_value,?number.value)) ????????for?i?in?xrange(1,?6): ????????????number.value?+=?add_value ????????????print?("***************add{0}?has?added***********".format(add_value)) ????????????time.sleep(1) ????????????print?("add{0}?number?=?{1}".format(add_value,?number.value)) ????except?Exception?as?e: ????????raise?e ???????? if?__name__?==?"__main__": ????number?=?multiprocessing.Value(‘i‘,?0) ????p1?=?multiprocessing.Process(target=add,args=(number,?1)) ????p2?=?multiprocessing.Process(target=add,args=(number,?3)) ????p1.start() ????p2.start() ????print?("main?end")
打印結果:
main?end init?add1?number?=?0 ***************add1?has?added*********** init?add3?number?=?1 ***************add3?has?added*********** add1?number?=?4 ***************add1?has?added*********** add3?number?=?5 ***************add3?has?added*********** add1?number?=?8 ***************add1?has?added*********** add3?number?=?9 ***************add3?has?added*********** add1?number?=?12 ***************add1?has?added*********** add3?number?=?13 ***************add3?has?added*********** add1?number?=?16 ***************add1?has?added*********** add3?number?=?17 ***************add3?has?added*********** add1?number?=?20 add3?number?=?20
再給加上鎖:
加1的進程加完後,再執行加上3的進程
import?multiprocessing import?time def?add(number,add_value,lock): ????lock.acquire() ????try: ????????print?("init?add{0}?number?=?{1}".format(add_value,?number.value)) ????????for?i?in?xrange(1,?6): ????????????number.value?+=?add_value ????????????print?("***************add{0}?has?added***********".format(add_value)) ????????????time.sleep(1) ????????????print?("add{0}?number?=?{1}".format(add_value,?number.value)) ????except?Exception?as?e: ????????raise?e ????finally: ????????lock.release() ???????? if?__name__?==?"__main__": ????lock?=?multiprocessing.Lock() ????number?=?multiprocessing.Value(‘i‘,?0) ????p1?=?multiprocessing.Process(target=add,args=(number,?1,?lock)) ????p2?=?multiprocessing.Process(target=add,args=(number,?3,?lock)) ????p1.start() ????p2.start() ????print?("main?end")
執行結果(對比上面):
main?end init?add1?number?=?0 ***************add1?has?added*********** add1?number?=?1 ***************add1?has?added*********** add1?number?=?2 ***************add1?has?added*********** add1?number?=?3 ***************add1?has?added*********** add1?number?=?4 ***************add1?has?added*********** add1?number?=?5 init?add3?number?=?5 ***************add3?has?added*********** add3?number?=?8 ***************add3?has?added*********** add3?number?=?11 ***************add3?has?added*********** add3?number?=?14 ***************add3?has?added*********** add3?number?=?17 ***************add3?has?added*********** add3?number?=?20
多進程共享內存實現:
import?multiprocessing import?time def?add(number,add_value,lock): ????lock.acquire() ????try: ????????print?("init?add{0}?number?=?{1}".format(add_value,?number.value)) ????????for?i?in?xrange(1,?6): ????????????number.value?+=?add_value ????????????print?("***************add{0}?has?added***********".format(add_value)) ????????????time.sleep(1) ????????????print?("add{0}?number?=?{1}".format(add_value,?number.value)) ????????except?Exception?as?e: ????????????raise?e ????????finally: ????????????lock.release() def?change(arr): ????for?i?in?range(len(arr)): ????????arr[i]?=?-arr[i] ???????? if?__name__?==?"__main__": ????lock?=?multiprocessing.Lock() ????number?=?multiprocessing.Value(‘i‘,?0) ????arr?=?multiprocessing.Array(‘i‘,?range(10)) ????print?(arr[:]) ????p1?=?multiprocessing.Process(target=add,args=(number,?1,?lock)) ????p2?=?multiprocessing.Process(target=add,args=(number,?3,?lock)) ????p3?=?multiprocessing.Process(target=change,args=(arr,)) ????p1.start() ????p2.start() ????p3.start() ????p3.join() ????print?(arr[:]) ????print?("main?end")
結果:
[0,?1,?2,?3,?4,?5,?6,?7,?8,?9] init?add3?number?=?0 ***************add3?has?added*********** [0,?-1,?-2,?-3,?-4,?-5,?-6,?-7,?-8,?-9] main?end add3?number?=?3 ***************add3?has?added*********** add3?number?=?6 ***************add3?has?added*********** add3?number?=?9 ***************add3?has?added*********** add3?number?=?12 ***************add3?has?added*********** add3?number?=?15 init?add1?number?=?15 ***************add1?has?added*********** add1?number?=?16 ***************add1?has?added*********** add1?number?=?17 ***************add1?has?added*********** add1?number?=?18 ***************add1?has?added*********** add1?number?=?19 ***************add1?has?added*********** add1?number?=?20
37. Python 多進程鎖 多進程共享內存