python学习笔记 day37 Manager

1. Manager可以提供进程之间共享的数据类型(list dict等)

先撇开进程,单纯看一下使用Manager创建一个dict的例子(只不过使用Manager创建的dict,进程之间都可以使用)

from multiprocessing import Manager
from multiprocessing import Process
if __name__=="__main__":
    m=Manager()  # 实例化一个Manage对象
    d=m.dict({"count":100})     # 使用Manager创建一个dict只不过这个字典可以在进程之间共享数据
    d["name"]="xuanxuan"
    print(d)

运行结果:

2. 使用Manager创建进程之间共享的dict:

from multiprocessing import Manager
from multiprocessing import Process
import random
import time

def func(d):  # 子进程执行的函数
    print(d)
    d["count"]-=1  # 如果Manager创建的dict可以在进程之间共享数据,那么开多个进程执行func函数,字典的count每次都会减一操作
    time.sleep(random.random())
if __name__=="__main__":
    m=Manager()   # 实例化一个Manager对象
    d=m.dict({"count":10})  # 使用Manager对象m创建了一个进程之间可以共享数据的字典d,并初始化未{"count":10}
    for i in range(10):
        p=Process(target=func,args=(d,))
        p.start()
        p.join()   # 判断进程是否结束,只有该子进程结束,才开下一个子进程(这样就变为同步的了) ,必须要加上这一句,否则打印出来的不对
        d["name"] = "xuanxuan"  # 第一个进程执行完之后,给d增加键值对,其他进程会接受到

运行结果:

 (注意这里打印的是开启进程打印本次减之前的count值,第一个进程打印的10 接下来减一,,,最后开10个进程,最终得到的d count应该减10次变为0的,这里count=1是第十次减之前的,打印完之后才进行减一操作)

 3. 使用Manager创建的进程之间共享的dict,异步实现进程之间通信:

from multiprocessing import Manager
from multiprocessing import Process
import time
import random

def func(d):
    # print(d)
    d["count"]-=1
    time.sleep(random.random())

if __name__=="__main__":
    m=Manager()
    d=m.dict({"count":10})
    P=[]  # 存放开启的进程
    for i in range(10):
        p=Process(target=func,args=(d,))
        p.start()
        # p.join()   # 判断该子进程是否结束,结束了才会继续开下一个进程(所以这样就会变成同步的)
        P.append(p)  # 把开启的进程放在列表中
    [p.join() for p in P]  # 把刚才开的10个进程放在列表,该语句执行代表开的10个进程全部结束
    print(d)  # 实现异步,就不再是开一个结束一个,再开下一个进程这样的同步过程,所有进程全都打开,然后一起判断结束,就是西安了异步

运行结果:

正常情况下开启10个子进程,减10次得到的应该是0,但是这里异步实现之后,得到的count变为1 说明好像少减了一次,其实是两个进程在同一时间操作func中的字典d数据,两者同时进行减一操作,减完了放回去,但是效果其实就是减了一次(比如两个进程同时拿到的count为7 都进行减一操作,都把count变为6,都放回去,所以表面上看 ,这两个进程相当于只进行了一次减一操作)

这就造成了数据的不安全,所以使用Manager创建的进程之间共享数据的dict是不安全的,有可能多个进程同时操作数据,所以应该加锁:

from multiprocessing import Process
from multiprocessing import Manager
from multiprocessing import Lock
import random
import time

def func(d,lock):  # 子进程执行该函数,但是每一个子进程拿到之后会先拿一把钥匙,占用资源,其他进程只能等待该进程执行完毕,释放钥匙,这就保证了开多个进程数据安全
    lock.acquire()  # 进程加锁,进程执行到func先获得锁,使得同一时间只有一个进程可以操作func,等进程执行完d["count"]-=1 再释放锁
    d["count"]-=1
    time.sleep(random.random())
    lock.release()

if __name__=="__main__":
    m=Manager()
    d=m.dict({"count":10})
    lock=Lock()
    P=[]  # 存放开的进程,等到所有进程都结束,而不是开一个进程,判断结束,再开下一个进程造成的同步,一下开很多进程,最后一起判断结束这样可以实现异步
    for i in range(10):
        p=Process(target=func,args=(d,lock))
        p.start()
        P.append(p)
    [p.join() for p in P]  # 开的多个进程,一起判断进程是否结束(这里一定要判断进程是否结束,否则会报错,不知道为什么Eva-)
    print(d)  # 加了锁之后,这样数据就安全了,同一时间只有一个进程可以操作func,所以不会出现两个进程同时操作dict的count的情况,加锁之后得到的d["count"]一定是0

 运行结果:

猜你喜欢

转载自www.cnblogs.com/xuanxuanlove/p/9783648.html