并发编程之进程同步

并发编程之进程同步

锁(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'\033[32m进程{i}买到了一张票!\033[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('\033[31m红灯亮了\033[0m')
        else:
            e.set()
            print('\033[32m绿灯亮了\033[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在等待。。。
.
.
.

'''
posted @ 2019-09-16 19:26  SweetJack  阅读(284)  评论(0编辑  收藏  举报