Python并发编程基础 №③ 信号量(Semaphore),事件(Event),生产者消费者模型 队列(Queue, JoinableQueue)

1.信号量(Semaphore)愿意是旗语,控制一个时刻可以多个进程一起访问

  被保护的代码(或数据),是锁的升级版本!


以进ktv包房举例:

 1 import time, random
 2 from multiprocessing import Process, Semaphore
 3 
 4 
 5 def enter_ktv(i, sp):
 6     sp.acquire()
 7     print('顾客%s进入了ktv!'%i)
 8     time.sleep(random.randint(i, 19))
 9     print('顾客%s走出了ktv!'%i)
10     sp.release()
11 
12 
13 if __name__ == '__main__':
14     sp = Semaphore(6)
15     for i in range(18):
16         Process(target=enter_ktv, args=(i, sp)).start()

2、事件(Event)

  (1)demo  

 1 import time, random
 2 from multiprocessing import Process
 3 from multiprocessing import Event
 4 
 5 e = Event()
 6 
 7 print(e.is_set())  # False 为阻塞状态
 8 
 9 # if not e.is_set():
10 #     e.wait()      # 是否阻塞,只有当is_set为False时才阻塞
11 
12 e.set()   # 设置状态为非阻塞
13 e.wait()
14 
15 e.clear()   # 设置状态为阻塞
16 
17 e.wait()
18 print('128888')
(2)模拟红绿灯系统
 1 def car_run(e, idx):
 2     if not e.is_set():
 3         print('\33[31m car:%s 停在十字路口,等待绿灯放行!\33[0m' % idx)
 4         e.wait()  # 阻塞 直到得到一个 事件状态变成 True 的信号
 5     print('car:%s 通过十字路口!' % idx)
 6 
 7 def traffic_light(e):
 8     while 1:
 9         if e.is_set():  # 逻辑与车的相反!
10             e.clear()
11             print('\33[31m红灯亮了\33[0m')
12         else:
13             e.set()
14             print('\33[32m绿灯亮了\33[0m')
15         time.sleep(3)
16 
17 
18 if __name__ == '__main__':
19     e = Event()
20     light = Process(target=traffic_light, args=(e, ))
21     light.start()
22 
23     for i in range(20):
24         car = Process(target=car_run, args=(e, i))
25         car.start()
26         time.sleep(random.random())

总结:

   A、设置状态:set() 和 clear()

   B、查看状态: is_set()默认创建时为False,即阻塞

     C、阻塞行为:wait() 根据is_set()来决定是否阻塞,False时阻塞,否则放行!

 

3、进程间的数据传递:Queue

进程间的数据传递可以使用队列,不过不是queue,而是multiprocessing模块中的Queue
 1 def consume(idx, q):
 2     time.sleep(random.randint(1,2))
 3     knife = q.get()
 4     print('\033[32m游侠%s,拿到一把:%s\033[0m'%(idx, knife))
 5 
 6 
 7 def produce(name, q):
 8     for i in range(10):
 9         time.sleep(random.random())
10         knife = '\033[31m%s做出了一件屠龙宝刀,编号:No%d\033[0m'%(name, i)
11         print(knife)
12         q.put(knife)
13 
14 
15 if __name__ == '__main__':
16     q = Queue()
17 
18     Process(target=produce, args=('Tom', q)).start()
19 
20     for i in range(10):
21         Process(target=consume, args=(i, q)).start()

 

4、生产者消费者模型

 

 1 # 生产者和消费者模型
 2 import time, random
 3 from multiprocessing import Process, Queue
 4 
 5 
 6 def produce(q, name):
 7     """
 8     生产者的生成行为
 9     :return: 产品
10     """
11     for i in range(10):
12         product = '%s生产了产品%d'%(name, i)
13         print(product)
14         q.put(product)
15         time.sleep(random.random())
16 
17 
18 def consume(q, name):
19     """
20     消费者的消费行为
21     :param q:
22     :return: None
23     """
24     while 1:
25         p = q.get()
26         if p is None:
27             print('%s消费时,发现没有东西了!'%name)
28             break
29         print('%s消费了-----%s'%(name, p))
30         time.sleep(random.random())
31 
32 
33 if __name__ == "__main__":
34     q = Queue()
35     p1 = Process(target=produce, args=(q, 'John'))
36     p1.start()
37     p2 = Process(target=produce, args=(q, 'Tom'))
38     p2.start()
39     c1 = Process(target=consume, args=(q, '童姥'))
40     c1.start()
41     c2 = Process(target=consume, args=(q, '远方'))
42     c2.start()
43     p1.join()
44     p2.join()
45     q.put(None)
46     q.put(None)
View Code

 

5、JoinableQueue完美解决上述问题

 1 import time, random
 2 from multiprocessing import Process
 3 from multiprocessing import JoinableQueue
 4 
 5 
 6 def produce(jq):
 7     for i in range(10):
 8         msg = '记者%d,写了一篇关于太空探索的报告'%i
 9         print(msg)
10         jq.put(msg)
11     jq.join()   # 阻塞  直到一个队列中的所有数据 全部被处理完毕
12 
13 
14 def consume(jq, i):
15     while 1:
16         msg = jq.get()
17         print('编辑%s审核了报告:%s'%(i,msg))
18         time.sleep(random.randint(1, 3))
19         jq.task_done()
20 
21 
22 if __name__ == '__main__':
23     jq = JoinableQueue()
24 
25     p = Process(target=produce, args=(jq, ))
26     p.start()
27 
28     c1 = Process(target=consume, args=(jq, 'c1'))
29     c2 = Process(target=consume, args=(jq, 'c2'))
30     c1.daemon = True
31     c2.daemon = True
32     c1.start()
33     c2.start()
34 
35     p.join()
View Code
posted @ 2019-12-26 23:18  四方游览  阅读(284)  评论(0编辑  收藏  举报