我们使用多线程访问一个资源,但有时候需要限制总数。例如连接池,支持同时连接,但数目是固定的。这些连接可以使用Semaphore来管理。
我们假设这样一个场景:
一个餐馆,只能允许指定数量的人同时用餐,超出的人要等待其他人用餐完毕才能用餐。
代码示例:
import logging
import random
import time
from threading import Thread, Semaphore
logging.basicConfig(level=logging.DEBUG, format='%(threadName)s-%(asctime)s-%(message)s')
class Restaurant:
def __init__(self, seat_count):
self.seat_count = seat_count # 餐位数量
def eating(self):
logging.debug("用餐中。。。")
time.sleep(random.randint(2, 5)) # 用餐时间随机2~5秒
logging.debug("用餐完成")
def eating(s: Semaphore, r: Restaurant):
with s:
r.eating()
if __name__ == '__main__':
r = Restaurant(5) # 最多5人同时用餐
s = Semaphore(r.seat_count) # 限制同时吃饭的人数量为餐位数量
for i in range(10): # 10个人需要用餐
t = Thread(target=eating, name=f'顾客{i}', args=(s, r))
t.start()
结果:
顾客0-2022-06-27 14:45:30,778-用餐中。。。
顾客1-2022-06-27 14:45:30,779-用餐中。。。
顾客2-2022-06-27 14:45:30,779-用餐中。。。
顾客3-2022-06-27 14:45:30,780-用餐中。。。
顾客4-2022-06-27 14:45:30,780-用餐中。。。
顾客2-2022-06-27 14:45:33,780-用餐完成
顾客5-2022-06-27 14:45:33,780-用餐中。。。
顾客1-2022-06-27 14:45:34,789-用餐完成
顾客4-2022-06-27 14:45:34,789-用餐完成
顾客6-2022-06-27 14:45:34,789-用餐中。。。
顾客7-2022-06-27 14:45:34,789-用餐中。。。
顾客3-2022-06-27 14:45:35,786-用餐完成
顾客0-2022-06-27 14:45:35,786-用餐完成
顾客8-2022-06-27 14:45:35,787-用餐中。。。
顾客9-2022-06-27 14:45:35,787-用餐中。。。
顾客6-2022-06-27 14:45:37,793-用餐完成
顾客5-2022-06-27 14:45:38,782-用餐完成
顾客8-2022-06-27 14:45:39,788-用餐完成
顾客7-2022-06-27 14:45:39,803-用餐完成
顾客9-2022-06-27 14:45:40,799-用餐完成
通过结果,我们可以看到,最多会有5个人同时用餐,有人用餐完成后,马上会有新的顾客用餐,满足我们的场景要求。