(十)并发编辑----(二)
目录
10.1信号量multiprocessing.Semaphore
10.1信号量multiprocessing.Semaphore
锁:同一个代码被一个进程使用
信号量:同一个代码被n个进程使用
from multiprocessing import Semaphore
from multiprocessing import process
import time
def func(i,sem):
sem.acquire() # 获取钥匙
print('\033[32m%s走进ktv\033[0m'%i)
time.sleep(random.randint(1,5))
print('%s走出ktv'%i)
sem.release() # 放回钥匙
if __name__ == '__main__':
sem = Semaphore(2) #两把钥匙
for i in range(10):
p = Process(target=func,args=(i,sem))
p.start()
10.2事件multiprocessing.Event
一个信号可以使所有的进程都进入阻塞状态也,可以控制所有的进程解除阻塞
set 和 clear:分别用来修改一个事件的状态 True或者False
is_set:用来查看一个事件的状态
wait 是依据事件的状态来决定自己是否在wait处阻塞 False阻塞 True不阻塞
from multiprocessing import Event
一个事件被创建之后,默认是阻塞状态
e = Event() # 创建了一个事件
print(e.is_set()) # 查看一个事件的状态,默认被设置成阻塞
e.set() # 将这个事件的状态改为True
print(e.is_set())
e.wait() # 是依据e.is_set()的值来决定是否阻塞的
print(123456)
e.clear() # 将这个事件的状态改为False
print(e.is_set())
e.wait() # 等待 事件的信号被变成True
print('*'*10)
'''
False
True
123456
False
'''
红绿灯问题
import time
import random
from multiprocessing import Event,Process
def cars(e,i):
if not e.is_set():
print('car%i在等待'%i)
e.wait() # 阻塞 直到得到一个 事件状态变成 True 的信号
print('car%i通过' % 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()
traffic = Process(target=light,args=(e,))
traffic.start()
for i in range(20):
car = Process(target=cars, args=(e,i))
car.start()
time.sleep(random.random())
10.3队列multiprocessing.Queue
from multiprocessing import Queue,Process
def produce(q):
q.put('hello')
def consume(q):
print(q.get())
if __name__ == '__main__':
q = Queue()
p = Process(target=produce,args=(q,))
p.start()
c = Process(target=consume, args=(q,))
c.start()
生产者消费者模型
简单版
def consumer(q, name):
while True:
food = q.get()
if food is None:
print('%s获取到了一个空' % name)
break
print('\033[31m%s消费了%s\033[0m' % (name, food))
time.sleep(random.randint(1, 3))
def producer(name, food, q):
for i in range(4):
time.sleep(random.randint(1, 3))
f = '%s生产了%s%s' % (name, food, i)
print(f)
q.put(f)
if __name__ == '__main__':
q = Queue(20)
p1 = Process(target=producer, args=('A', '包子', q))
p2 = Process(target=producer, args=('B', '泔水', q))
c1 = Process(target=consumer, args=(q, 'C'))
c2 = Process(target=consumer, args=(q, 'D'))
p1.start()
p2.start()
c1.start()
c2.start()
p1.join()
p2.join()
q.put(None)
q.put(None)
升级版
在消费者这一端: 每次获取一个数据,处理一个数据,发送一个记号 : 标志一个数据被处理成功
在生产者这一端: 每一次生产一个数据, 且每一次生产的数据都放在队列中,在队列中刻上一个记号
当生产者全部生产完毕之后, join信号 : 已经停止生产数据了,且要等待之前被刻上的记号都被消费完,当数据都被处理完时,join阻塞结束
consumer中把所有的任务消耗完,producer端的join感知到,停止阻塞,所有的producer进程结束,主进程中的p.join结束,主进程中代码结束,守护进程(消费者的进程)结束
import time
import random
from multiprocessing import Process,JoinableQueue
def consumer(q,name):
while True:
food = q.get()
print('\033[31m%s消费了%s\033[0m' % (name,food))
time.sleep(random.randint(1,3))
q.task_done() # count - 1
def producer(name,food,q):
for i in range(4):
time.sleep(random.randint(1,3))
f = '%s生产了%s%s'%(name,food,i)
print(f)
q.put(f)
q.join() # 阻塞 直到一个队列中的所有数据 全部被处理完毕
if __name__ == '__main__':
q = JoinableQueue(20)
p1 = Process(target=producer, args=('A', '包子', q))
p2 = Process(target=producer, args=('B', '泔水', q))
c1 = Process(target=consumer, args=(q, 'C'))
c2 = Process(target=consumer, args=(q, 'D'))
p1.start()
p2.start()
c1.daemon = True # 设置为守护进程 主进程中的代码执行完毕之后,子进程自动结束
c2.daemon = True
c1.start()
c2.start()
p1.join()
p2.join() # 感知一个进程的结束