pow 函数使用 ThreadPoolExecutor 阻塞所有线程

2024-02-28

尽管关于 ThreadPoolExecutor 的第一个示例使用了 pow 函数(https://docs.python.org/3/library/concurrent.futures.html https://docs.python.org/3/library/concurrent.futures.html)似乎使用 pow 在调用时会异常阻塞所有线程。请参阅下面的代码。

from concurrent.futures import ThreadPoolExecutor
import time

executor = ThreadPoolExecutor(max_workers=16)

def blocking():
    i = 0
    while True:
        time.sleep(1)
        i+=1
        print("block",i)
        if i>3:
            print("Starting pow....")
            break
    block= pow(363,100000000000000)
    return True

def non_blocking():
    i = 0
    while True:
        time.sleep(1)
        i+=1
        print("non",i)

    return True

f1 = executor.submit(blocking)
f2 = executor.submit(non_blocking)

我期望的输出:

block 1
non 1
block 2
non 2
block 3
non 3
block 4
Starting pow....
non 4
non 5
non 6
non 7
non 8

但程序在“starting pow....”后停止运行,给出结果:

block 1
non 1
block 2
non 2
block 3
non 3
block 4
Starting pow....

你的Python实现(可能是CPython)必须有一个全局解释器锁 https://wiki.python.org/moin/GlobalInterpreterLock (GIL)

pow是一个原生 Python 函数,它在调用时不会释放 GIL,从而在运行且运行相当长一段时间时有效地阻止所有执行。

如果你想要非阻塞,请使用ProcessPoolExecutor https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.ProcessPoolExecutor反而。一个单独的进程意味着 2 个单独的 GIL 并且不会阻塞。它具有完全相同的界面。它也有更多的限制,因为它需要参数可腌制的(没有像线程那样方便的共享内存)

请注意,此计算可能永远不会结束或以“内存不足错误”结束:因为它是整数之间的幂big幂值,因此它不会像浮点数那样溢出,而是不断计算,每次创建越来越大的整数

该数字的估计位数大致为:

>>> math.log10(363)*100000000000000
255990662503611.25

10^14 位数字比当前任何计算机可以处理的内存和 CPU 数量都要多。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

pow 函数使用 ThreadPoolExecutor 阻塞所有线程 的相关文章

随机推荐