geekdoc-python-zh/docs/pythonland/50.md

4.2 KiB
Raw Permalink Blame History

Python GIL(全局解释器锁)

原文:https://python.land/python-concurrency/the-python-gil

Python 有一个特性,这使得并发编程更加困难。它被称为 Python GIL 是全局解释器锁的缩写。GIL 确保任何时候都只有一个线程在运行。因为一次只能运行一个线程,所以不可能使用多个带线程的处理器。但是不要担心,有一种方法可以解决这个问题,使用多处理库

目录

线程安全

如前所述, Python 线程共享相同的内存。由于多个线程同时运行,我们不知道线程访问共享数据的顺序。因此,访问共享数据的结果取决于调度算法。这个算法决定哪个线程何时运行。线程“竞相”访问/更改数据。

Thread safety

Thread-safe code only manipulates shared data in such a way, that it does not interfere with other threads.

发明 GIL 是因为 CPython 的内存管理不是线程安全的。由于一次只运行一个线程CPython 可以放心,永远不会出现竞争情况。

竞赛条件的演示

举个例子,让我们创建一个名为a的共享 Python 变量,值为 2:

a = 2

现在假设我们有两个线程,线程 1 和线程 2。它们执行以下操作:

  • 线程 _ 一:a = a + 2
  • 线程 _ 二:a = a * 3

如果 thread_one 能够首先访问a,然后 thread_two 能够访问,那么结果将是:

  • a = 2 + 2a现在是 4。
  • a = 4 * 3a现在是 12。

Thank you for reading my tutorials. I write these in my free time, and it requires a lot of time and effort. I use ads to keep writing these free articles, I hope you understand! Support me by disabling your adblocker on my website or, alternatively, buy me some coffee. It's much appreciated and allows me to keep working on this site!

但是,如果碰巧 thread_two 先运行,然后 thread_one 运行,我们会得到不同的输出:

  • a = 2 * 3a现在是 6
  • aa = 6+2现在是 8

因此,执行顺序显然对输出有影响。然而,还有一个更糟糕的结果!如果两个线程同时读取变量a,做它们自己的事,然后赋新值,会怎么样?他们都会看到 a = 2。取决于谁先写出它的结果a 最终会是 4 或 6。不是我们所期望的这就是我们所说的竞争条件。

Race condition

The condition of a system where the systems behavior is dependent on the sequence or timing of other, uncontrollable events. 

竞争条件很难发现,尤其是对于不熟悉这些问题的软件工程师来说。此外,它们往往随机发生,导致不稳定和不可预测的行为。众所周知,这些错误很难发现和调试。这正是 Python 有 GIL 的原因——让大多数 Python 用户的生活更轻松。

我们能摆脱蟒蛇 GIL 吗?

如果 GIL 在并发性方面阻碍了我们,我们难道不应该摆脱它或者关闭它吗?没那么容易。其他特性、库和包已经开始依赖 GIL所以必须有东西来取代它否则整个生态系统将会崩溃。这是一个很难解决的问题。如果你感兴趣你可以在 Python wiki 上阅读更多相关内容。

2021 年 Python GIL 的最新进展

最近,有人通过提供一个去除了 GIL 的很有前途的概念验证 CPython 版本重新开始了讨论。这个概念验证的源代码可以在 Github 这里找到。作者附上了一份综合文件,解释了该操作的细节和特点。对于那些想更多了解这个主题的人来说,这是一本有趣的读物。