繁体   English   中英

python线程如何工作?

[英]How does a python thread work?

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

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

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

这是一个复杂的问题,需要大量说明。 我将继续使用CPython只是因为它是使用最广泛的,也是我的经验。

  • Python线程是系统线程,它需要Python解释器本地在运行时将其内容执行为字节码。 GIL是特定于解释器的(在本例中为CPython)锁,它强制每个线程在解释器上获取一个锁,从而防止两个线程同时运行,无论它们位于哪个内核上。

  • 任何 CPU内核一次都不能运行一个以上的线程。 需要多个内核才能明智地谈论并行性。 并发与并行性并不相同-前者意味着两个线程之间的操作可以在其中一个线程完成之前进行交错,但是其中两个线程都不需要同时启动,而后者则意味着可以同时启动 如果这使您感到困惑,请在此处获得有关区别的更好描述。

  • 有多种方法可以在单核CPU中引入并发性,即让线程挂起(使自己进入睡眠状态)并在需要时恢复运行,但是没有办法在单核中引入并行性。

由于这些事实,因此要视情况而定。

  • 系统线程本质上被设计为可并发的-否则,拥有操作系统就没有多大意义了。 它们是否实际上以这种方式执行取决于任务:在某处是否有原子锁? (正如我们将看到的那样!)

  • 执行CPU限制计算的线程-在其中执行大量代码,并且同时为每一行动态调用解释器-在GIL上获得了一个锁,以防止其他线程执行该锁。 因此,在这种情况下,所有内核一次只能工作一个线程,因为没有其他线程可以获取解释器。

    话虽这么说,线程不需要保持GIL,直到他们完成,而不是采集数据并在需要时为/解除锁定。 这是可能的两个线程交错他们的行动,因为GIL可以在一个代码块,由其他线程抓住年底发布,在代码块结束时释放,等等。 它们不会并行运行-但是它们当然可以并行运行。

  • 另一方面,I / O绑定线程仅在等待请求完成时就花费大量时间。 这些线程不获取GIL-为什么在没有什么可解释的情况下为什么要使用它们? -因此可以肯定,您可以有多个并行运行的I / O等待线程,每个线程一个核心。 分钟代码需要编译为字节码,但是,(也许您需要处理您的请求?)GIL再次上升。

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

结果

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

就交错原子操作而言,所有线程都可以并行运行。 这些交织到底有多原子 ?在代码块之后释放了GIL吗? 每行之后? -取决于任务和线程。 Python线程不必串行执行-一个线程完成,然后另一个启动-因此在这种意义上并发。

在CPython中,这些线程是真实的OS线程,并被调度为由操作系统并发运行。 但是,正如您所指出的,GIL意味着一次仅一个线程将在执行指令。

让我解释一下这一切的含义。 线程在同一虚拟机内运行,因此在同一物理机上运行。 进程可以在同一台物理计算机上运行,​​也可以在另一台物理计算机上运行。 如果您围绕线程构建应用程序,则您无济于事可访问多台计算机。 因此,您可以扩展到一台计算机上的多个内核(随着时间的推移,内核数量会增加很多),但是要真正达到Web规模,您还是需要解决多计算机问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM