10.3.10 限制资源的并发访问
有时可能需要允许多个工作线程同时访问一个资源,但要限制总数。例如,连接池支持同时连接,但数目可能是固定的,或者一个网络应用可能支持固定数目的并发下载。这些连接就可以使用Semaphore来管理。
import logging
import random
import threading
import time
class ActivePool():
def __init__(self):
super(ActivePool,self).__init__()
self.active = []
self.lock = threading.Lock()
def makeActive(self,name):
with self.lock:
self.active.append(name)
logging.debug('Running: %s',self.active)
def makeInactive(self,name):
with self.lock:
self.active.remove(name)
logging.debug('Running: %s',self.active)
def worker(s,pool):
logging.debug('Waiting to join the pool')
with s:
name = threading.current_thread().getName()
pool.makeActive(name)
time.sleep(0.1)
pool.makeInactive(name)
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s (%(threadName)-2s) %(message)s',
)
pool = ActivePool()
s = threading.Semaphore(2)
for i in range(4):
t = threading.Thread(
target=worker,
name=str(i),
args=(s,pool),
)
t.start()
在这个例子中,ActivePool类只作为一种便利方法,用来跟踪某个给定时刻哪些线程能够运行。真正的资源池会为新的活动线程分配一个连接或另外某个值,并且当这个线程工作完成时再回收这个值。在这里,资源池指示用来保存活动线程的名,以显示至少有两个线程在并发运行。
运行结果: