37. 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
转载于:https://blog.51cto.com/286577399/2049535