为什么Python';s GIL执行严格的处理顺序?

为什么Python';s GIL执行严格的处理顺序?,python,multithreading,python-3.x,python-multithreading,gil,Python,Multithreading,Python 3.x,Python Multithreading,Gil,使用python3运行: from concurrent.futures import ThreadPoolExecutor, as_completed def main(): with ThreadPoolExecutor(max_workers=16) as producersPool: for i in [1,2,3,4,5,6,7,8,9,0]: producersPool.submit((lambda i : print(i))(i))

使用python3运行:

from concurrent.futures import ThreadPoolExecutor, as_completed

def main():
    with ThreadPoolExecutor(max_workers=16) as producersPool:
        for i in [1,2,3,4,5,6,7,8,9,0]:
            producersPool.submit((lambda i : print(i))(i))


if __name__ == "__main__":
    main()
总是一样的

现在我希望你能正确地理解我的意思——我不一定希望这些任务被重新排序,但我只是想知道为什么会发生排序?我的意思是,人们可以期望在一个线程内以确定性的方式完成任务,但是线程的严格排队对我来说似乎有点奇怪

无论如何,如何在Python3中获得真正的并发性?(据我所知,Jython和IronPython只支持2.x)。

所有作业都是在提交之前执行的,它们中没有一个只会写入输出流。您提交调用每个
lambda
的结果

即使您使用:

1
2
3
4
5
6
7
8
9
0
每个线程中没有足够的内容可被另一个线程抢占,因此它们都在任何其他线程进入之前完成。

所有作业在提交之前都会执行,并且它们都只会写入输出流。您提交调用每个
lambda
的结果

即使您使用:

1
2
3
4
5
6
7
8
9
0

每个线程中没有足够的线程可被另一个线程抢占,因此它们都在其他线程进入之前完成。

回答问题的第二部分:

“如何在Python 3中获得真正的并发性?”

您可以使用以下模块:

“多处理是一个包,它支持使用 与线程模块类似的API。多处理程序包 同时提供本地和远程并发性,有效地进行侧步 全局解释器通过使用子进程而不是线程来锁定。“


由于您的示例使用了
concurrent.futures
中的
ThreadPoolExecutor
,请查看同一软件包中的内容。它类似于
ThreadPoolExecutor
,但使用进程(而不是线程),因此不会受到GIL的阻碍。

回答问题的第二部分:

“如何在Python 3中获得真正的并发性?”

您可以使用以下模块:

“多处理是一个包,它支持使用 与线程模块类似的API。多处理程序包 同时提供本地和远程并发性,有效地进行侧步 全局解释器通过使用子进程而不是线程来锁定。“


由于您的示例使用了
concurrent.futures
中的
ThreadPoolExecutor
,请查看同一软件包中的内容。它类似于
ThreadPoolExecutor
,但使用进程(而不是线程),因此它不会受到GIL的阻碍。

啊,我明白了。好吧,我添加了
sleep(5)
,现在它似乎以一种真正随机的方式打印列表。谢谢。示例中的实际问题是打印发生在主线程中,OP只向线程池提交
None
。请参阅我对@l4mpi的评论(lambdas在这里看起来有点邋遢,所以我创建了一个函数)。啊,我明白了。好吧,我添加了
sleep(5)
,现在它似乎以一种真正随机的方式打印列表。谢谢。示例中的实际问题是打印发生在主线程中,OP从不向线程池提交除
None
之外的任何内容……请参阅我对@l4mpi的评论(lambdas在这里看起来有点邋遢,所以我创建了一个函数)。您的示例包含一个重要错误:您实际上正在调用lambda,并且只将结果(始终为无)传递给
submit
。观察到的行为与线程池无关。你可能想写
(lambda i:(lambda:print(i)))(i)
。@l4mpi,是的,我已经注意到了,并且已经击中了自己的脸。我将代码编辑为
producersPool.submit(sleepy,I)
,它按预期运行,即是一种相当不可预测的方式。谢谢。您的示例包含一个重要错误:您实际上正在调用lambda,并且只将结果(始终为无)传递给
submit
。观察到的行为与线程池无关。你可能想写
(lambda i:(lambda:print(i)))(i)
。@l4mpi,是的,我已经注意到了,并且已经击中了自己的脸。我将代码编辑为
producersPool.submit(sleepy,I)
,它按预期运行,即是一种相当不可预测的方式。谢谢。是的,我看到了,但是我没有考虑到可能性。太好了,很抱歉我不能一次接受两个答案(我不应该一次问两个:))是的,我看到了,但只是没有考虑到可能性。太好了,很抱歉我不能同时接受两个答案(我不应该一次问两个:)