37. Python 多进程锁 多进程共享内存

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 给我们提供了 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 多进程锁 多进程共享内存的主要内容,如果未能解决你的问题,请参考以下文章

8-1多进程锁和共享内存

python 归纳 (二十)_多进程数据共享和同步_共享内存Value & Array

python-- 多进程的基本语法 进程间数据交互与共享进程锁和进程池的使用

[Python3] 043 多线程 简介

Python 3 并发编程多进程之进程同步(锁)

python 归纳 (二四)_多进程数据共享和同步_锁Lock&RLock