【问题标题】:Why does Python's GIL enforce strict ordering of processing?为什么 Python 的 GIL 强制执行严格的处理顺序?
【发布时间】:2013-12-21 16:26:11
【问题描述】:
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运行:

1
2
3
4
5
6
7
8
9
0

始终如一。

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

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

【问题讨论】:

  • 您的示例包含一个重要错误:您实际上是在 calling lambda 并且仅将 result(始终为 None)传递给 @987654323 @。观察到的行为与 ThreadPool 无关。你可能想改写(lambda i: (lambda: print(i)))(i)
  • @l4mpi,是的,我已经注意到了,并且已经打了自己的脸。我将代码编辑为producersPool.submit(sleepy, i),它按预期运行,即是一种相当出人意料的方式。谢谢。

标签: python multithreading python-3.x python-multithreading gil


【解决方案1】:

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

即使你使用过:

producersPool.submit(lambda i: print(i), (i,))

每个线程中没有足够的被另一个线程抢占,所以它们都在任何其他线程之前完成。

【讨论】:

  • 啊,我明白了。好吧,我添加了sleep(5),它现在似乎以真正随机的方式打印列表。谢谢。
  • 示例中的实际问题是打印发生在主线程中,并且OP从不向线程池提交除None之外的任何内容...
  • 查看我对@l4mpi 的评论(IMO 在这里的 lambdas 看起来有点粗糙,所以我做了一个函数)。
【解决方案2】:

回答你问题的第二部分:

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

您可以使用multiprocessing 模块:

"multiprocessing 是一个支持使用 类似于 threading 模块的 API。多处理包 提供本地和远程并发,有效地回避 通过使用子进程而不是线程来获得全局解释器锁。”

由于您的示例使用了来自concurrent.futuresThreadPoolExecutor,因此请查看同一包中的ProcessPoolExecutor。它类似于ThreadPoolExecutor,但使用进程(而不是线程),因此不受 GIL 的阻碍。

【讨论】:

  • 是的,我看到了,只是没有想到这种可能性。太好了,很抱歉我不能同时接受两个答案(首先我不应该一次问两个:))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多