第十章:使用进程、线程和协程提供并发性-multiprocessing:像线程一样管理进程-控制资源的并发访问
10.4.14 控制资源的并发访问
有时可能需要允许多个工作进程同时访问一个资源,但要限制总数。例如,连接池支持同时连接,但数目可能是固定的,或者一个网络应用可能支持固定数目的并发下载。这些连接就可以使用Semaphore来管理。
import random
import multiprocessing
import time
class ActivePool:
def __init__(self):
super(ActivePool,self).__init__()
self.mgr = multiprocessing.Manager()
self.active = self.mgr.list()
self.lock = multiprocessing.Lock()
def makeActive(self,name):
with self.lock:
self.active.append(name)
def makeInactive(self,name):
with self.lock:
self.active.remove(name)
def __str__(self):
with self.lock:
return str(self.active)
def worker(s,pool):
name = multiprocessing.current_process().name
with s:
pool.makeActive(name)
print('Activating {} now running {}'.format(
name,pool))
time.sleep(random.random())
pool.makeInactive(name)
if __name__ == '__main__':
pool = ActivePool()
s = multiprocessing.Semaphore(3)
jobs = [
multiprocessing.Process(
target=worker,
name=str(i),
args=(s,pool),
)
for i in range(10)
]
for j in jobs:
j.start()
while True:
alive = 0
for j in jobs:
if j.is_alive():
alive += 1
j.join(timeout=0.1)
print('Now running {}'.format(pool))
if alive == 0:
# All done
break
在这个例子中,ActivePool类只作为一种便利方法,用来跟踪某个给定时刻哪些进程能够运行。真正的资源池会为新的活动进程分配一个连接或另外某个值,并且当这个进程工作完成时再回收这个值。在这里,资源池指示用来保存活动进程的名,以显示只有三个进程在并发运行。
运行结果: