• Python程序中的进程操作-进程同步(multiprocess.Lock)


    尽管并发编程让我们能更加充分的利用IO资源,但是也给我们带来了新的问题:当多个进程使用同一份数据资源的时候,就会引发数据安全或顺序混乱问题。

    一、进程同步

    多个进程同时执行,为了相互制约各进程对资源的访问,使得各个进程的执行相互同步。

    在我的理解里,进程同步也算是进程间通讯(ipc)的一种手段。

    二、为什么需要进程同步

    多进程会引发抢占资源的问题,为了解决这个问题就需要各进程之间相互同步,控制进程对关键资源的访问。

    在C语言中实现进程同步的方式有很多,比如:信号量,锁机制等。

    例子: 演示多进程资源抢占问题

    import os
    import time
    import random
    from multiprocessing import Process
    
    def work(n):
        print('%s: %s is running' %(n,os.getpid()))
        time.sleep(random.random())
        print('%s:%s is done' %(n,os.getpid()))
    
    if __name__ == '__main__':
        for i in range(3):
            p=Process(target=work,args=(i,))
            p.start()
    

    三、Python中实现进程同步

    1. 首先from multiprocessing import Lock
    2. 在主进程中,实例化得到锁,lock = Lock(),并传给子进程
    3. 在子进程中通过上锁和解锁实现对多进程对资源的控制。lock.acquire()上锁,lock.release()解锁

    演示:通过Python锁机制控制资源的访问

    def work(lock,n):
        print(f"等待开锁 进程{n}")
        # 上锁
        lock.acquire()     # 当上锁之后别的进程无法访问,会阻塞住
        print(f'进程{n} pid: %s is running' % ( os.getpid()))
        time.sleep(random.random())
        print(f'进程{n} pid: %s is done' % (os.getpid()))
        # 开锁
        lock.release()
    
    if __name__ == '__main__':
        lock=Lock() # 实例化得到锁
        for i in range(3):
            p=Process(target=work,args=(lock,i))
            p.start()
    

    等待开锁 进程1
    进程1 pid: 8696 is running
    等待开锁 进程0
    等待开锁 进程2
    进程1 pid: 8696 is done
    进程0 pid: 14264 is running
    进程0 pid: 14264 is done
    进程2 pid: 22724 is running
    进程2 pid: 22724 is done

    根据结果可以发现,在上锁之前的代码。多进程是并发访问的,但上锁之后,直到解锁后才能有第二个人访问。以此类推。就好像上厕所排队一样,进去一个人关上门锁上,第二个人等着。

    但是看完你会有个疑问,那被锁上的代码,每个进程在访问的时候不就是串行的依次在访问嘛。

    确实,锁机制 保证了数据的安全,但牺牲掉效率.

    四、多进程模拟同时抢票

    # 文件db的内容为:{"count":1}
    # 注意一定要用双引号,不然json无法识别
    # 并发运行,效率高,但竞争写同一文件,数据写入错乱
    from multiprocessing import Process,Lock
    import time,json,random
    def search():
        dic=json.load(open('db'))
        print('剩余票数%s' %dic['count'])
    
    def get():
        dic=json.load(open('db'))
        time.sleep(0.1)  # 模拟读数据的网络延迟
        if dic['count'] >0:
            dic['count']-=1
            time.sleep(0.2)  # 模拟写数据的网络延迟
            json.dump(dic,open('db','w'))
            print('购票成功')
    
    def task():
        search()
        get()
    
    if __name__ == '__main__':
        for i in range(100):  # 模拟并发100个客户端抢票
            p=Process(target=task)
            p.start()
    

    上述代码,你会发现多个进程在同时抢票,相互抢占文件资源,每个进程都把文件读入到内存中进行抢票。实际上,资源只能被一个人占有,这就会引发问题

    4.1 通过锁控制进程资源访问

    def search():
        time.sleep(1)
        with open("db","w",encoding="utf8") as f:
            data = json.load(f)
            print(f'还剩{data["count"]}')
    
    def get():
        with open('db','rt',encoding='utf-8') as f:
            res = json.load(f)
        time.sleep(1)  # 模拟网络io
        if res['count'] > 0:
            res['count'] -= 1
            with open('db', 'w', encoding='utf-8') as f:
                json.dump(res, f)
                print(f'进程{os.getpid()} 抢票成功')
            time.sleep(1.5)  # 模拟网络io
        else:
            print('票已经售空啦!!!!!!!!!!!')
    
    def task(lock):
        print(f"进程:{os.getpid()}  正在抢票中。。。")
    
        # 上锁     每个进程都会访问一遍,所以加锁就等于上锁到解锁这段代码是串行的
        lock.acquire()  # 当上锁之后别的进程无法访问,会阻塞住
        get()
        # 开锁
        lock.release()
    
    if __name__ == '__main__':
        # 创建锁
        lock = Lock()
    
        pro_list = []
        # 创建进程
        for i in range(10):
            p = Process(target=task, args=(lock,))
            p.start()
            pro_list.append(p)
        # 回收进程
        for i in range(10):
            pro_list[i].join()
    

    总结

    进程同步理论上应该是进程间通讯中的一部分,是一个大话题,每个语言也都有实现进程同步的需求。需要将各个进程对资源的访问加以限制。在各个语言中也都有限制。这里目前只介绍了这一种进程同步的方法。

    锁机制 是把锁住的代码变成了串行,保证了数据的安全,但牺牲掉效率.

  • 相关阅读:
    关于阿里云centos 2.6下手机表情输入后无法保存到mysql数据库的问题调研及mysql版本从5.1升级到5.7的全过程纪要
    EXTJS 5 学习笔记2
    EXTJS 5 学习笔记1
    关于java.lang.String理解中的一些难点
    关于centos7中使用rpm方式安装mysql5.7版本后无法使用root登录的问题
    大数据专栏
    过采样中用到的SMOTE算法
    linux后台执行命令:&和nohup
    P,R,F1 等性能度量(二分类、多分类)
    word2vec模型cbow与skip-gram的比较
  • 原文地址:https://www.cnblogs.com/XuChengNotes/p/11529599.html
Copyright © 2020-2023  润新知