python线程如何工作?

时间:2016-04-24 06:48:45

标签: python multithreading concurrency parallel-processing

我想知道python线程是同时还是并行运行?

例如,如果我有两个任务并在两个线程内运行它们会同时运行还是会被安排同时运行?

我知道 GIL 并且线程只使用一个CPU内核。

3 个答案:

答案 0 :(得分:3)

这是一个复杂的问题,需要大量的解释。我会坚持使用CPython,因为它是最广泛使用的,也是我经验丰富的。

  • Python线程是一个系统线程,它要求Python解释器本身在运行时将其内容执行到字节码。 GIL是一个特定于解释器(在本例中为CPython)的锁,它强制每个线程获取对解释器的锁定,防止两个线程同时运行,无论它们是什么核心&#39 ;继续。

  • CPU核心一次可以运行多个线程。您需要多个内核甚至可以合理地谈论并行性。并发性与并行性不同 - 前者意味着两个线程之间的操作可以在完成之前交错,但两个线程都不需要同时启动,而后者意味着可以启动的操作同时。如果这让您感到困惑,有关差异的更好描述是here

  • 有一些方法可以在单核CPU中引入并发 - 即,让线程暂停(让自己进入休眠状态)并在需要时恢复 - 但是有没有方式来介绍单核并行性。

由于这些事实,因此,这取决于。

  • 系统线程固有地设计为并发 - 否则就不会有更多的操作系统。它们是否实际以这种方式执行取决于任务:某处存在原子锁吗? (正如我们将要看到的那样!)

  • 执行CPU绑定计算的线程 - 执行大量代码,同时为每一行动态调用解释器 - 获取GIL锁定,防止其他线程执行相同操作。因此,在 情况下,所有核心中一次只能运行一个线程,因为没有其他线程可以获取解释器。

    话虽如此,线程需要保留GIL直到完成,而是在需要时获取并释放锁。两个线程可以交错它们的操作,因为GIL可以在代码块的末尾释放,由另一个线程抓取,在那个代码块的末尾释放,依此类推。他们不会在 parallel 中运行 - 但他们当然可以同时运行。

  • 另一方面,I / O绑定线程花费大量时间只是等待请求完成。这些线程没有获得GIL - 为什么他们会在什么时候无法解释? - 当然,你可以让多个I / O等待线程并行运行,每个线程一个核心。分钟代码需要编译成字节码,但是,(可能你需要处理你的请求?)再次进入GIL。

  • Python中的进程在GIL中存活,因为它们是与线程捆绑在一起的资源集合。每个进程都有自己的解释器,因此进程中的每个线程只需要与其自己的直接进程兄弟竞争GIL。这就是为什么基于流程的并行性是Python的推荐方法,尽管它总体上消耗了更多的资源。

Upshot

因此,如果他们不需要访问CPython解释器,那么两个线程中的两个任务可以并行中运行。如果他们正在等待I / O请求或正在使用外部函数接口使用不需要Python解释器的合适的其他语言(例如,C)扩展,则可能发生这种情况。

所有线程都可以在交错原子操作的意义上同时运行 。究竟如何原子这些交错可以 - 在代码块之后释放GIL吗?每一行之后? - 取决于任务和线程。 Python线程不必串行执行 - 一个线程完成,然后另一个线程启动 - 因此在这个意义上存在并发性。

答案 1 :(得分:1)

在CPython中,线程是真正的OS线程,并且被安排为由操作系统并发运行。但是,正如您所指出的那样,GIL意味着一次只有一个线程正在执行指令。

答案 2 :(得分:1)

让我解释一切意味着什么。线程在同一虚拟机内运行,因此在同一台物理机器上运行。进程可以在同一物理计算机或另一台物理计算机上运行。如果围绕线程构建应用程序,则无法访问多台计算机。因此,您可以扩展到单台计算机上的核心数量(随着时间的推移会有很多核心),但要真正达到网络规模,您无论如何都需要解决多机问题。