• 锁机制,信号机制,事件机制


    一.锁机制

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

    multiprocessing模块提供基于消息的ipc通信机制:队列和管道

      l = Lock()

      l.acquire() 锁,别的程序无法操作

      l.release()开锁,允许别的进程操作

    模拟抢票

    #文件db的内容为:{"count":1}
    #注意一定要用双引号,不然json无法识别
    #并发运行,效率高,但竞争写同一文件,数据写入错乱
    from multiprocessing import Process,Lock
    import time,json,random
    def search():
        dic=json.load(open('db'))
        print('33[43m剩余票数%s33[0m' %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('33[43m购票成功33[0m')
    
    def task():
        search()
        get()
    
    if __name__ == '__main__':
        for i in range(100): #模拟并发100个客户端抢票
            p=Process(target=task)
            p.start()
    
    多进程同时抢购余票
    多进程同时抢购余票
    #文件db的内容为:{"count":5}
    #注意一定要用双引号,不然json无法识别
    #并发运行,效率高,但竞争写同一文件,数据写入错乱
    from multiprocessing import Process,Lock
    import time,json,random
    def search():
        dic=json.load(open('db'))
        print('33[43m剩余票数%s33[0m' %dic['count'])
    
    def get():
        dic=json.load(open('db'))
        time.sleep(random.random()) #模拟读数据的网络延迟
        if dic['count'] >0:
            dic['count']-=1
            time.sleep(random.random()) #模拟写数据的网络延迟
            json.dump(dic,open('db','w'))
            print('33[32m购票成功33[0m')
        else:
            print('33[31m购票失败33[0m')
    
    def task(lock):
        search()
        lock.acquire()
        get()
        lock.release()
    
    if __name__ == '__main__':
        lock = Lock()
        for i in range(100): #模拟并发100个客户端抢票
            p=Process(target=task,args=(lock,))
            p.start()
    
    使用锁来保证数据安全
    使用锁来保证数据安全

    二.信号量

      sem = Semphore(3) 3表示可以有3个进程同时进行操作数据,而后面的进程必须等待前面的进程结束才可以进行

    from multiprocessing import Process,Semaphore
    import time,random
    
    def go_ktv(sem,user):
        sem.acquire()
        print('%s 占到一间ktv小屋' %user)
        time.sleep(random.randint(0,3)) #模拟每个人在ktv中待的时间不同
        sem.release()
    
    if __name__ == '__main__':
        sem=Semaphore(4)
        p_l=[]
        for i in range(13):
            p=Process(target=go_ktv,args=(sem,'user%s' %i,))
            p.start()
            p_l.append(p)
    
        for i in p_l:
            i.join()
        print('============》')
    
    例子

    三.事件

    e = Event

    四个方法 : e.set() 修改e.is_set为True  e.clear修改e.is_set为False  e.wait() 判断e.is_set是True还是

    False,True继续执行 False就会停止

    python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法 set  wait  clear

      事件处理的机制:全局定义了一个'Flag',如果'Flag'值为 False,那么当程序执行event.wait 方法时就会阻塞,如果'Flag'值为True,那么event.wait方法时便不再阻塞

    clear:将'Flag'设置为False

    set:将'Flag'设置为True

    from multiprocessing import Process, Event
    import time, random
    
    
    def car(e, n):
        while True:
            if not e.is_set():  # 进程刚开启,is_set()的值是Flase,模拟信号灯为红色
                print('33[31m红灯亮33[0m,car%s等着' % n)
                e.wait()    # 阻塞,等待is_set()的值变成True,模拟信号灯为绿色
                print('33[32m车%s 看见绿灯亮了33[0m' % n)
                time.sleep(random.randint(3, 6))
                if not e.is_set():   #如果is_set()的值是Flase,也就是红灯,仍然回到while语句开始
                    continue
                print('车开远了,car', n)
                break
    
    
    def police_car(e, n):
        while True:
            if not e.is_set():# 进程刚开启,is_set()的值是Flase,模拟信号灯为红色
                print('33[31m红灯亮33[0m,car%s等着' % n)
                e.wait(0.1) # 阻塞,等待设置等待时间,等待0.1s之后没有等到绿灯就闯红灯走了
                if not e.is_set():
                    print('33[33m红灯,警车先走33[0m,car %s' % n)
                else:
                    print('33[33;46m绿灯,警车走33[0m,car %s' % n)
            break
    
    
    
    def traffic_lights(e, inverval):
        while True:
            time.sleep(inverval)
            if e.is_set():
                print('######', e.is_set())
                e.clear()  # ---->将is_set()的值设置为False
            else:
                e.set()    # ---->将is_set()的值设置为True
                print('***********',e.is_set())
    
    
    if __name__ == '__main__':
        e = Event()
        for i in range(10):
            p=Process(target=car,args=(e,i,))  # 创建是个进程控制10辆车
            p.start()
    
        for i in range(5):
            p = Process(target=police_car, args=(e, i,))  # 创建5个进程控制5辆警车
            p.start()
        t = Process(target=traffic_lights, args=(e, 10))  # 创建一个进程控制红绿灯
        t.start()
    
        print('============》')
    
    红绿灯实例
  • 相关阅读:
    [BZOJ4825][HNOI2017]单旋(线段树+Splay)
    [BZOJ4542][HNOI2016]大数(莫队)
    [LOJ6281]数列分块入门 5
    [LOJ6280]数列分块入门 4
    [LOJ6279]数列分块入门 3
    [LOJ6278]数列分块入门 2
    [LOJ6277]数列分块入门 1
    [BZOJ2120]数颜色
    [BZOJ3585]mex
    [ZJb417]区间众数
  • 原文地址:https://www.cnblogs.com/wangjian941118/p/9513333.html
Copyright © 2020-2023  润新知