代码之家  ›  专栏  ›  技术社区  ›  jdd

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

  •  78
  • jdd  · 技术社区  · 18 年前

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

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

    7 回复  |  直到 16 年前
        1
  •  53
  •   jmq ryanshow    13 年前

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

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

    pyprocessing PEP 还包括一些有趣的基准测试。

        2
  •  36
  •   Jason Baker    13 年前

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

    如果你想提高响应性,你应该考虑使用线程。不过,还有其他选择,即 microthreading . 您还应该研究一些框架:

        3
  •  21
  •   Peter Mortensen Pieter Jan Bonestroo    16 年前

    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类扩展了线程,然后实现 run start() 跑 方法

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

        4
  •  12
  •   anekix    8 年前

    无论我提到哪里 thread 我的意思是特别的 python中的线程

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

    由于python中的内存管理不是线程安全的,因此每个线程都需要独占访问python解释器中的数据结构 GIL .

    Why does python use GIL?

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

    其思想是每当执行线程时 (即使是主线) ,获取GIL,并在预定义的时间间隔后

    Why not simply remove GIL?

    因此,消除GIL的成本是通过降低单线程应用程序的性能来支付的,这是从来都不需要的。

    So when does thread switching occurs in python?

    线程切换发生在GIL被释放时。那么什么时候GIL被释放呢? 有两种情况需要考虑。

    如果线程正在执行CPU限制的操作(例如图像处理)。

    在较旧版本的python中,线程切换通常发生在固定数量的python指令之后 100 。事实证明,决定何时切换不是一个很好的策略,因为执行单个指令所花费的时间可能 非常疯狂,从毫秒到甚至一秒。因此,在每次 100 无论指令执行所需的时间如何,这都是一个糟糕的策略。

    在新版本中,使用可配置的时间间隔,而不是使用指令计数作为切换线程的指标。 sys.getswitchinterval() . 这可以使用 sys.setswitchinterval()

    如果线程正在执行某些IO绑定操作(例如文件系统访问或
    网络(IO)

    每当线程等待IO操作完成时,就会释放GIL。

    Which thread to switch to next?

    解释器没有自己的调度程序。在间隔结束时调度哪个线程是由操作系统决定的。

        5
  •  10
  •   Ben McNiel    18 年前

    IPC python框架或选择其他语言。

        6
  •  3
  •   willt    12 年前

    解决GIL的一个简单方法是 multiprocessing 它还可以轻松地扩展到多台物理机器。

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

        7
  •  2
  •   phreaki    17 年前

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