• 并发编程之进程同步


    并发编程之进程同步

    锁(Lock)

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

    # ticket.txt
    '''{"count":2}'''
    
    from multiprocessing import Process,Lock
    import time,json
    
    def buy(i,lock):
        lock.acquire()
        with open(r'ticket','r',encoding='utf8') as f:
            data = json.load(f)
            print(f'余票:{data["ticket"]}')
        if data['ticket']>0:
            data['ticket']-=1
            print(f'33[32m进程{i}买到了一张票!33[0m')
        else:
            print('票已售空!')
        time.sleep(0.5)
        with open('ticket','w') as f:
            json.dump(data,f)
        lock.release()
    
    if __name__ == '__main__':
        lock = Lock()
        for i in range(10):
            p = Process(target=buy,args=(i,lock))
            p.start()
    

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

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

    信号量(semaphore)

    信号量:

      互斥锁Lock 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。

    import time
    import random
    from multiprocessing import Process,Semaphore
    
    def ktv(i,sem):
        sem.acquire()
        print(f'{i}走进ktv开始唱歌。。。')
        time.sleep(random.randint(2,4))
        print(f'{i}唱歌结束离开ktv。。。')
        sem.release()
    
    if __name__ == '__main__':
        sem =Semaphore(4)  # 给ktv加锁,一次性只能n个人同时访问主进程。
        for i in range(10):
            p = Process(target=ktv,args=(i,sem))
            p.start()
    

    事件(Even)

    • 通过一个信号来控制多个进程同时执行或者阻塞
    • 一个信号可以使所有的进程都进入阻塞状态
    • 也可以控制所有的进程结束阻塞
    • 一个事件被创建之后,默认是阻塞状态

    set() 和clear()
    修改一个事件的状态:True 或者False
    is_set()
    用来查看一个事件的状态
    wait()
    根据事件的状态来决定是否阻塞

    实例:模拟车辆过红绿灯

    import time
    from multiprocessing import Process,Event
    import random
    
    def car(e,i):
        if not e.is_set():
            print(f'car{i}在等待。。。')
            e.wait()
        print(f'car{i}通过')
    
    def light(e):
        while True:
            if e.is_set():
                e.clear()
                print('33[31m红灯亮了33[0m')
            else:
                e.set()
                print('33[32m绿灯亮了33[0m')
            time.sleep(2)
    
    if __name__ == '__main__':
        e = Event()
        p = Process(target=light,args=(e,))
        p.start()
        for i in range(1000):
            c = Process(target=car,args=(e,i))
            c.start()
            time.sleep(random.random())
    '''
    绿灯亮了
    car0通过
    car1通过
    car2通过
    红灯亮了
    car3在等待。。。
    car4在等待。。。
    car5在等待。。。
    car6在等待。。。
    .
    .
    .
    
    '''
    
  • 相关阅读:
    Django-配置Mysql
    Django-manage.py shell命令
    Codeforces 1516B AGAGA XOOORRR
    sitemesh入门教程
    养生好习惯
    解决idea自动导入类String总是导入sun.org.apache.xpath.internal.operations包下的String
    [C#]浅谈协变与逆变
    [C#]跨模块的可选参数与常量注意事项
    [C#]LockBits使用笔记
    1.在校研究生申请软件著作权(学校为第一著作人)
  • 原文地址:https://www.cnblogs.com/dadazunzhe/p/11529172.html
Copyright © 2020-2023  润新知