线程在Python中是如何工作的,Python线程特有的常见陷阱是什么?

线程在Python中是如何工作的,Python线程特有的常见陷阱是什么?,python,multithreading,Python,Multithreading,我一直在想Python中线程是如何工作的,很难找到关于线程如何工作的好信息。我可能只是缺少了一个链接或什么的,但官方文件似乎对这个问题不是很透彻,而且我还没有找到一篇好的评论 据我所知,一次只能运行一个线程,活动线程每隔10条指令左右切换一次 哪里有好的解释,或者你能提供一个吗?了解在Python中使用线程时遇到的常见问题也很好。下面是一个基本的线程示例。它将产生20个线程;每个线程将输出其线程编号。运行它并观察它们的打印顺序 import threading class Foo (thread

我一直在想Python中线程是如何工作的,很难找到关于线程如何工作的好信息。我可能只是缺少了一个链接或什么的,但官方文件似乎对这个问题不是很透彻,而且我还没有找到一篇好的评论

据我所知,一次只能运行一个线程,活动线程每隔10条指令左右切换一次


哪里有好的解释,或者你能提供一个吗?了解在Python中使用线程时遇到的常见问题也很好。

下面是一个基本的线程示例。它将产生20个线程;每个线程将输出其线程编号。运行它并观察它们的打印顺序

import threading
class Foo (threading.Thread):
    def __init__(self,x):
        self.__x = x
        threading.Thread.__init__(self)
    def run (self):
          print str(self.__x)

for x in xrange(20):
    Foo(x).start()
正如您所暗示的,Python线程是通过时间切片实现的。这就是它们获得“平行”效应的方式

在我的示例中,我的Foo类扩展了thread,然后实现了
run
方法,这就是您希望在线程中运行的代码所在的位置。要启动线程,请在thread对象上调用
start()
,该对象将自动调用
run
方法


当然,这只是最基本的。您最终会想了解线程同步和消息传递的信号量、互斥量和锁。

Python是一种非常容易执行线程的语言,但有一些注意事项。您需要知道的最大的事情是全局解释器锁。这只允许一个线程访问解释器。这意味着两件事:1)在python中很少使用lock语句;2)如果要利用多处理器系统,必须使用单独的进程。编辑:我还应该指出,如果您也想绕过GIL,可以将一些代码放在C/C++中

因此,您需要重新考虑为什么要使用线程。如果你想使你的应用程序并行化以利用双核架构,你需要考虑把你的应用程序分成多个进程。 <>如果你想提高响应性,你应该考虑使用线程。不过,还有其他选择,即。您还应该研究一些框架:


  • 是的,由于全局解释器锁(GIL),一次只能运行一个线程。以下是一些关于这方面的见解的链接:

    在最后一个链接中,有一句有趣的话:

    让我解释一下这一切意味着什么。 线程在同一虚拟机内运行 机器,因此在同一机器上运行 物理机器。进程可以运行 在同一物理机器上或在 另一台物理机器。如果你 构建您的应用程序 线程,你没有做任何访问 多台机器。因此,您可以进行缩放 到单个磁盘上的多个磁芯 机器(这将是相当多的 随着时间的推移),但要真正接触网络 天平,你需要解决这个问题 多台机器的问题


    如果要使用多核,请定义一个基于进程的API来执行真正的并行化。还包括一些有趣的基准测试。

    如果单个工人正在执行I/O绑定操作,则使用python中的线程。如果您试图在一台机器上跨多个内核进行扩展,请为python找到一个好的框架或选择一种不同的语言。

    请记住,GIL设置为每隔一段时间轮询一次,以便显示多个任务的外观。这个设置可以微调,但我建议线程应该做一些工作,否则大量的上下文切换将导致问题


    我甚至建议在处理器上使用多个父处理器,并尝试将类似的作业保留在同一个核心上。

    GIL的一个简单解决方案是模块。它可以作为线程模块的替代品,但使用多个解释器进程而不是线程。正因为如此,对于简单的事情来说,它的开销比普通线程稍微多一些,但是如果需要的话,它提供了真正并行化的优势。 它还可以轻松地扩展到多台物理机器


    如果你真的需要大规模并行化,我会看得更远,但是如果你只想扩展到一台计算机的所有核心或几个不同的核心,而不需要所有的工作来实现一个更全面的框架,这是给你的。

    注意:无论我在哪里提到
    thread
    我都是指python中的线程,直到明确说明为止

    如果您来自
    C/C++
    background,那么线程在python中的工作方式会略有不同。在python中,在给定的时间内只能有一个线程处于运行状态。这意味着python中的线程无法真正利用多个处理内核的功能,因为按照设计,线程不可能在多个内核上并行运行

    由于python中的内存管理不是线程安全的,因此每个线程都需要独占访问python解释器中的数据结构。这种独占访问是通过一种称为GIL(全局解释器锁)的机制获得的

    python为什么使用GIL?

    以防止多个线程同时访问解释器状态并破坏解释器状态

    其思想是每当执行一个线程时(即使它是主线程),都会获取一个GIL,并在某个预定义的时间间隔之后执行 GIL由当前线程释放,并由其他线程(如果有的话)重新获取

    为什么不干脆删除GIL?

    这并不是说不可能删除GIL,而是因为在这样做的过程中,我们最终在内部设置了多个锁