并发编程之进程同步
并发编程之进程同步
锁(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在等待。。。
.
.
.
'''