• python中的进程(二)


    一 : 概述

      当多个进程同时访问一个变量或者一个文件的时候,可能会发生数据紊乱的问题,为了解决这个问题,便有了锁这个工具.

    二 : 锁的创建和使用

      使用到的锁也是在multiprocessing包中的Lock类,要使用锁将它实例化即可.

      锁可以使得一个变量或文件在同时只能有一个进程访问,相当于给变量(或文件)加了一把锁,当该进程使用完毕,将锁释放之后,其他进程才可以访问.

    from multiprocessing import Process,Lock
    import time
    
    def check(i):
        with open('余票') as f:
            con = f.read()
        print('第%s个人查到余票还剩%s张'%(i,con))
    
    def buy_ticket(i,l):
        l.acquire()# 拿钥匙,锁门
        with open('余票') as f:
            con = int(f.read())
            time.sleep(0.1)
        if con > 0:
            print('33[31m 第%s个人买到票了33[0m'%i)
            con -= 1
        else:
            print('33[32m 第%s个人没有买到票33[0m'%i)
        time.sleep(0.1)# 是指 买完票后,把余票数量重写写入数据库的时间延迟
        with open('余票','w') as f:
            f.write(str(con))
        l.release()# 还钥匙,开门
    
    if __name__ == '__main__':
        l = Lock()
        for i in range(10):
            p_ch = Process(target=check,args=(i+1,))
            p_ch.start()
        for i in range(10):
            p_buy = Process(target=buy_ticket,args=(i+1,l))
            p_buy.start()

      对象的acquire()方法可以加锁,release()可以释放锁,将需要加锁的代码块放在这两句中间即可.

    三 : 信号量的创建和使用

      有时候,我们需要多个进程同时访问一个方法,但是又要对他们加以控制,换个说法,也就是需要一个有多把钥匙的锁,这时候我们需要信号量(Semaphore)

      使用方法和Lock一致,不同的是实例化的时候需要传入一个int类型的参数,也就是创建几把钥匙,加锁和释放的方法也和lock一致,非常简单.

    from multiprocessing import Process,Semaphore
    import time
    
    def func(i,sem):
        sem.acquire()
        print('第%s个人进入小黑屋,拿了钥匙锁上门' % i)
        time.sleep(1)
        print('第%s个人出去小黑屋,还了钥匙打开门' % i)
        sem.release()
    
    if __name__ == '__main__':
        sem = Semaphore(5)# 初始化了一把锁5把钥匙,也就是说允许5个人同时进入小黑屋
        # 之后其他人必须等待,等有人从小黑屋出来,还了钥匙,才能允许后边的人进入
        for i in range(20):
            p = Process(target=func,args=(i,sem,))
            p.start()

    四 : 事件的创建和使用

      为了使用主进程控制子进程,创建了事件机制.要使用事件,需要导入multiprocessing包中的Event,通过几个方法控制来事件.

      事件处理的机制:全局定义一个flag(event.is_set()),如果为False,那么程序执行event.wait()的时候就会阻塞,为True,则不阻塞.

      事件的方法:

        set() : 将flag设为True

        clear() : 将flag设为False

        is_set() : 返回flag的值

      下面用一个红绿灯函数来演示事件的使用

    def tra(e):
        '''信号灯函数'''
        while 1:# 红绿灯得一直亮着,要么是红灯要么是绿灯
            if e.is_set():# True,代表绿灯亮,那么此时代表可以过车
                time.sleep(5)# 所以在这让灯等5秒钟,这段时间让车过
                print('33[31m 红灯亮! 33[0m')# 绿灯亮了5秒后应该提示到红灯亮
                e.clear()# 把is_set设置为False
            else:
                time.sleep(5)# 此时代表红灯亮了,此时应该红灯亮5秒,在此等5秒
                print('33[32m 绿灯亮! 33[0m')# 红的亮够5秒后,该绿灯亮了
                e.set()# 将is_set设置为True
    
    def Car(i,e):
        e.wait()# 车等在红绿灯,此时要看是红灯还是绿灯,如果is_set为True就是绿灯,此时可以过车
        print('第%s辆车过去了'%i)
    
    if __name__ == '__main__':
        e = Event()
        triff_light = Process(target=tra,args=(e,))# 信号灯的进程
        triff_light.start()
        for i in range(50):# 描述50辆车的进程
            if i % 3 == 0:
                time.sleep(2)
            car = Process(target=Car,args=(i+1,e,))
            car.start()
  • 相关阅读:
    [BZOJ 1295][SCOI2009]最长距离(SPFA+暴力)
    [BZOJ 3143][HNOI2013]游走(数学期望)
    [BZOJ 1797][AHOI2009]最小割(最小割关键边的判断)
    [BZOJ1876][SDOI2009]superGCD(高精度)
    [BZOJ1801][AHOI2009]中国象棋(递推)
    [bzoj2245][SDOI2011]工作安排(费用流)
    [bzoj 1064][NOI2008]假面舞会(dfs判断环)
    [BZOJ 1486][HNOI2009]最小圈(二分答案+dfs写的spfa判负环)
    2.3、操纵json、parquet、jdbc数据库
    输入框中的添加回车事件
  • 原文地址:https://www.cnblogs.com/DoingBe/p/9519203.html
Copyright © 2020-2023  润新知