多进程操作-进程锁multiprocess.Lock的使用

多进程操作-进程锁multiprocess.Lock的使用

​ 通过之前的Process模块的学习,我们实现了并发编程,虽然更加充分地利用了IO资源,但是也有缺陷:当多个进程共用一份数据资源的时候,就会引发数据数据安全或者顺序混乱的问题。

​ 如上问题,我们就引入了进程锁来维护执行顺序

​ 以模拟抢票为例,看看数据安全的重要性:

from  multiprocessing import Process,Lock
import json,time,os

# 获取剩余票数
def search():
    time.sleep(1) # 模拟网络io(网络延迟)
    with open('db.txt','rt',encoding='utf-8') as fr:
        res = json.load(fr)
        # print(res)
        print(f"还剩{res['count']}")

def get():
    with open('db.txt','rt',encoding='utf-8') as fr:
        res = json.load(fr)

    time.sleep(1)  # 模拟网络io(网络延迟)
    if res['count'] > 0 :
        res['count'] -= 1
        with open('db.txt','wt',encoding='utf-8') as fw:
            json.dump(res,fw)
            print(f'进程{os.getpid()} 抢票成功')
        time.sleep(1)   # 模拟网络io(网络延迟)

    else:
        print('票已经售空了!!!')

def func(lock):
    search()

    # 锁住
    lock.acquire()
    get()
    lock.release()


if __name__ == '__main__':
    lock = Lock()  # 写在主进程是为了让子进程拿到一把锁
    for i in range(10):
        p = Process(target=func,args=(lock,))
        p.start()
        # p.join()

# 进程锁 是把锁住的代码变成了串行
# join 是把所有非子进程变成了串行

# 为了保证数据的安全,串行牺牲掉了效率

加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,即串行的修改,没错,速度是慢了,但牺牲了速度却保证了数据安全。

虽然可以用文件共享数据实现进程间通信,但问题是:

  1. 效率低(共享数据基于文件,而文件是硬盘上的数据)
  2. 需要自己加锁处理

因此我们最好找寻一种解决方案能够兼顾:

  1. 效率高(多个进程共享一块内存的数据)
  2. 帮我们处理好锁问题。这就是mutiprocessing模块为我们提供的基于消息的IPC通信机制:队列和管道。

队列和管道都是将数据存放于内存中,队列又是基于(管道+锁)实现的,可以让我们从复杂的锁问题中解脱出来,我们应该尽量避免使用共享数据,尽可能使用消息传递和队列,避免处理复杂的同步和锁问题,而且在进程数目增多时,往往可以获得更好的可获展性。

posted @ 2019-09-16 16:16  tomjoy  阅读(1997)  评论(0编辑  收藏  举报