• 锁,信号量 ,事件 Event模块


    1. 锁 

    Lock模块: 保证一段代码,在同一时刻只能被一个进程执行.
        lock = Lock()    创造了一把锁
        acquire()       获取锁的钥匙
        release()    归还这把锁的钥匙
      ps: 多进程的数据的不安全性: 当多个进程共享一段数据的时候, 数据会出现不安全的现象, 需要加锁, 来维护数据的安全性.

     例: 

      抢票:

    抢票分析: 
          客户可以同一时间访问服务器,并且访问到 同一个余票数
         当客户发出购买请求, 服务器必须进行同步处理, 一个一个来. 
    
    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()
    

       银行同时取钱.存钱:

    from multiprocessing import Process,Value,Lock
    import time
    
    
    def get_money(num,l):# 取钱
        l.acquire()# 拿走钥匙,锁上门,不允许其他人进屋
        for i in range(100):
            num.value -= 1
            print(num.value)
            time.sleep(0.01)
        l.release()# 还钥匙,打开门,允许其他人进屋
    
    def put_money(num,l):# 存钱
        l.acquire()
        for i in range(100):
            num.value += 1
            print(num.value)
            time.sleep(0.01)
        l.release()
    
    if __name__ == '__main__':
        num = Value('i',100)
        l = Lock()
        p = Process(target=get_money,args=(num,l))
        p.start()
        p1 = Process(target=put_money, args=(num,l))
        p1.start()
        p.join()
        p1.join()
        print(num.value)
    

      

    2, 信号量 

    Semaphore模块: 多把钥匙 对应一把锁

        本质就是: lock+count 计数 来实现的

    sem = Semaphore(n)
    n : 是指初始化一把锁配几把钥匙,一个int型
    拿钥匙,锁门 l.acquire()
    还钥匙,开门 l.release()
    信号量机制比锁机制多了一个计数器,这个计数器是用来记录当前剩余几把钥匙的。
    当计数器为0时,表示没有钥匙了,此时acquire()处于阻塞。
    对于计数器来说,每acquire一次,计数器内部就减1,release一次,计数器就加1
    例:
      发廊:
    from multiprocessing import Process,Semaphore
    import time
    import random
    
    def func(i,sem):
        sem.acquire()
        print('33[31m 第%s个人进入小黑屋,拿了钥匙锁上门33[0m' % i)
        time.sleep(random.randint(3,5))
        print('33[32m 第%s个人出去小黑屋,还了钥匙打开门 33[0m' % 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()
    

    3, 事件 Event模块: 

     标志:在 事件创立之初,标志默认为False

     wait(timeout=None) 等待 有一个关键字参数 timeout(超时) 以秒为单位.

    e = Event()
    # e.set() #将is_set()设为True
    # e.clear() # 将is_set()设为False
    # e.wait() #判断is_set的bool值,如果bool为True,则非阻塞,bool值为False,则阻塞
    # e.is_set() # 标识
    # 事件是通过is_set()的bool值,去标识e.wait() 的阻塞状态
    # 当is_set()的bool值为False时,e.wait()是阻塞状态
    # 当is_set()的bool值为True时,e.wait()是非阻塞状态
    # 当使用set()时,是把is_set的bool变为True
    # 当使用clear()时,是把is_set的bool变为False
    例:  
    信号灯:
    from multiprocessing import Process,Event
    import time
    import random
    
    def tra(e):
        '''信号灯函数'''
        # e.set()
        # print('33[32m 绿灯亮! 33[0m')
        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()
    

      

  • 相关阅读:
    linux下配置java环境
    CentOS6 配置静态IP
    数据库的事务
    MySQL总论
    JDBC面试题
    scp命令
    大数据练习题
    Linux下的Mysql安装 & 配置
    Hive的安装配置 & 基础指令
    本地存储localStorage以及它的封装接口store.js的使用
  • 原文地址:https://www.cnblogs.com/123zzy/p/9513686.html
Copyright © 2020-2023  润新知