Python多进程池(multiprocessing Pool)是否线程安全?

5

我有一个Django项目。如果我创建一个包含Pool()对象的变量,并尝试从Django视图中使用该池(以并行方式运行),这种方式是否是线程安全的?还有其他方法可以实现吗?

from multiprocessing import Pool
general_executor_pool = Pool()
2个回答

7
我通过谷歌发现这个问题,因为我也在问同样的问题。从经验上来说,我可以说不是,因为我最近调试了一段遭受竞态条件影响的软件。下面是具体过程:
1. 主进程循环运行,并每隔3分钟在新线程中生成一个包含约1000个账户的多进程池。 2. 线程调用multiprocessing.Pool(max_processes=32),pool.map(func, accounts)。这将打开32个进程,然后逐个将每个账户应用于可用进程。 3. 原作者并不知道,这个过程所需时间远超过3分钟。那么下一次生成线程以创建多进程池时会发生什么?它会为总共64个进程生成32个新进程吗?实际上并不是这样。相反,我的结果被打乱了,并表明多个线程以不确定的方式对我的数据进行操作。
我想跟踪multiprocessing模块,看看它是否设计成非线程安全的,或者从专业人士那里得到答案。至少,根据我的经验,我亲眼见证了它不是线程安全的。

0

值得一提的是,我不得不检查这个问题,而 multiprocessing.pool.Pool 确实是线程安全的。 下面的代码不会触发 AssertionError (已在 Python 3.6.9 上测试):

import random
import time
import multiprocessing.pool
from threading import Thread

pool = multiprocessing.pool.Pool()

def return_value(value):
    time.sleep(random.random())
    return value
count = 100
def call_return_value():
    counter_start = random.randint(0, 100)
    result = list(range(counter_start, counter_start + count))
    pool_result = pool.imap_unordered(return_value, range(counter_start, counter_start + count), chunksize=1)
    pool_result = list(pool_result)
    assert set(pool_result) == set(result)
tl = [Thread(target=call_return_value) for _ in range(24)]
for t in tl:
    t.start()

基本上,这段代码启动了一个进程池,并通过该池启动了24个线程,这些线程通过调用return_value函数返回值。此函数在等待随机延迟(0到1秒之间)后返回值。

当然,pool_result不再有序,但它包含了正确的元素集合,对于所有线程都是如此:值不会混合。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接