How do threads work in Python, and what are common Python-threading specific pitfalls?我一直在努力围绕Python中线程的工作方式,很难找到有关它们如何运行的良好信息。我可能只是缺少链接之类的东西,但似乎官方文档对该主题的了解不是很全面,而且我也找不到很好的文章。 据我所知,一次只能运行一个线程,活动线程每10条指令左右切换一次? 哪里有很好的解释,或者您可以提供一个解释?知道在使用Python线程时遇到的常见问题也将非常高兴。 是的,由于全局解释器锁定(GIL),一次只能运行一个线程。以下是一些有关此方面的见解的链接:
在最后一个链接中有一个有趣的报价:
如果要使用多核,则pyprocessing定义基于进程的API进行真正的并行化。 PEP还包括一些有趣的基准。 Python是一种相当容易使用的语言,但是有一些警告。您需要了解的最大信息是全局解释器锁定。这仅允许一个线程访问解释器。这意味着两件事:1)您很少在python中使用过lock语句; 2)如果您想利用多处理器系统,则必须使用单独的进程。编辑:我还应该指出,如果您也想绕开GIL,可以将一些代码放在C / C中。 因此,您需要重新考虑为什么要使用线程。如果要并行化应用程序以利用双核体系结构,则需要考虑将应用程序分解为多个进程。 如果要提高响应速度,则应考虑使用线程。但是,还有其他选择,即微线程。您还应该研究一些框架:
下面是一个基本的线程示例。它将产生20个线程;每个线程将输出其线程号。运行它,并观察其打印顺序。
正如您所暗示的,Python线程是通过时间切片实现的。这就是他们获得"平行"效果的方式。 在我的示例中,我的Foo类扩展了线程,然后实现了 当然,这只是基础知识。您最终将想要了解有关线程同步和消息传递的信号量,互斥量和锁。 如果单个工作人员正在执行I / O绑定操作,请在python中使用线程。如果要在计算机上跨多个内核扩展,请为python找到一个好的IPC框架,或者选择其他语言。 注意:无论我在何处提及 如果您来自 由于python中的内存管理不是线程安全的,因此每个线程都需要对python解释器中的数据结构进行独占访问。此独占访问是通过称为 为了防止多个线程同时访问解释器状态并破坏解释器状态。 这个想法是每当执行一个线程(即使它是主线程)时,就会获取一个GIL,并且在预定的时间间隔后, 并不是不可能删除GIL,而是这样做,我们最终将多个锁放入解释器中以序列化访问,这甚至使单线程应用程序的性能降低。 因此删除GIL的成本是通过降低单线程应用程序的性能来弥补的,这是绝对不希望的。 GIL释放时发生线程切换。那么GIL何时释放? 如果线程正在执行CPU绑定操作(Ex图像处理)。 在旧版本的python中,线程切换通常是在固定数量的python指令之后发生的,默认情况下设置为 在新版本中,不是使用指令计数作为切换线程的度量标准,而是使用了可配置的时间间隔。 进行更改 如果线程正在执行某些IO绑定操作(例如文件系统访问权限或 只要线程正在等待一些IO操作完成,就会释放GIL。 解释器没有自己的调度程序。在间隔结束时调度哪个线程是操作系统的决定。 。 GIL的一个简单解决方案是多处理模块。它可以用作线程模块的替代品,但使用多个解释器进程而不是线程。因此,与简单线程相比,简单事务的开销要大一些,但是如果需要,它可以为您带来真正的并行化的优势。 如果您需要真正的大规模并行化,而我只是想进一步扩展一下,但是如果您只想扩展到一台计算机或几个不同内核的所有内核,而无需花很多时间来实现一个更全面的框架,那么是给你的。 请记住,GIL设置为经常轮询,以显示多个任务的外观。此设置可以微调,但是我建议应该进行一些工作,线程正在执行,或者许多上下文切换将导致问题。 我甚至会建议在处理器上有多个父级,并尝试将作业保持在相同的内核上。 |