1. 程式人生 > >37. Python 多進程鎖 多進程共享內存

37. Python 多進程鎖 多進程共享內存

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 給我們提供了 ValueArray 模塊,他們可以在不通的進程中共同使用


例子:不加鎖,讓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 多進程鎖 多進程共享內存