67 lines
4.2 KiB
Markdown
67 lines
4.2 KiB
Markdown
|
|
# Python GIL(全局解释器锁)
|
|||
|
|
|
|||
|
|
> 原文:[https://python.land/python-concurrency/the-python-gil](https://python.land/python-concurrency/the-python-gil)
|
|||
|
|
|
|||
|
|
Python 有一个特性,这使得并发编程更加困难。它被称为 Python **GIL** ,是全局解释器锁的缩写。GIL 确保任何时候都只有一个线程在运行。因为一次只能运行一个线程,所以不可能使用多个带线程的处理器。但是不要担心,有一种方法可以解决这个问题,[使用多处理库](https://python.land/python-concurrency/python-multiprocessing)。
|
|||
|
|
|
|||
|
|
目录
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
* [线程安全](#Thread-safety "Thread-safety")
|
|||
|
|
* [竞赛条件的演示](#A_demonstration_of_a_race_condition "A demonstration of a race condition")
|
|||
|
|
* 我们能摆脱蟒蛇 GIL 吗?
|
|||
|
|
* [2021 年 Python GIL 的最新进展](#Latest_Python_GIL_developments_in_2021 "Latest Python GIL developments in 2021")
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
## 线程安全
|
|||
|
|
|
|||
|
|
如前所述, [Python 线程](https://python.land/python-concurrency/python-threads)共享相同的内存。由于多个线程同时运行,我们不知道线程访问共享数据的顺序。因此,访问共享数据的结果取决于调度算法。这个算法决定哪个线程何时运行。线程“竞相”访问/更改数据。
|
|||
|
|
|
|||
|
|
**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 变量](https://python.land/introduction-to-python/variable),值为 2:
|
|||
|
|
|
|||
|
|
```py
|
|||
|
|
a = 2
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
现在假设我们有两个线程,线程 1 和线程 2。它们执行以下操作:
|
|||
|
|
|
|||
|
|
* 线程 _ 一:`a = a + 2`
|
|||
|
|
* 线程 _ 二:`a = a * 3`
|
|||
|
|
|
|||
|
|
如果 thread_one 能够首先访问`a`,然后 thread_two 能够访问,那么结果将是:
|
|||
|
|
|
|||
|
|
* a = 2 + 2,`a`现在是 4。
|
|||
|
|
* a = 4 * 3,`a`现在是 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](https://www.buymeacoffee.com/pythonland)**. It's much appreciated and allows me to keep working on this site!
|
|||
|
|
|
|||
|
|
但是,如果碰巧 thread_two 先运行,然后 thread_one 运行,我们会得到不同的输出:
|
|||
|
|
|
|||
|
|
* a = 2 * 3,`a`现在是 6
|
|||
|
|
* `a`a = 6+2,现在是 8
|
|||
|
|
|
|||
|
|
因此,执行顺序显然对输出有影响。然而,还有一个更糟糕的结果!如果两个线程同时读取变量`a`,做它们自己的事,然后赋新值,会怎么样?他们都会看到 a = 2。取决于谁先写出它的结果,a 最终会是 4 或 6。不是我们所期望的!这就是我们所说的竞争条件。
|
|||
|
|
|
|||
|
|
**Race condition**
|
|||
|
|
|
|||
|
|
The condition of a system where the system’s behavior is dependent on the sequence or timing of other, uncontrollable events.
|
|||
|
|
|
|||
|
|
竞争条件很难发现,尤其是对于不熟悉这些问题的软件工程师来说。此外,它们往往随机发生,导致不稳定和不可预测的行为。众所周知,这些错误很难发现和调试。这正是 Python 有 GIL 的原因——让大多数 Python 用户的生活更轻松。
|
|||
|
|
|
|||
|
|
## 我们能摆脱蟒蛇 GIL 吗?
|
|||
|
|
|
|||
|
|
如果 GIL 在并发性方面阻碍了我们,我们难道不应该摆脱它或者关闭它吗?没那么容易。其他特性、库和包已经开始依赖 GIL,所以必须有东西来取代它,否则整个生态系统将会崩溃。这是一个很难解决的问题。如果你感兴趣,你可以在 [Python wiki](https://wiki.python.org/moin/GlobalInterpreterLock) 上阅读更多相关内容。
|
|||
|
|
|
|||
|
|
## 2021 年 Python GIL 的最新进展
|
|||
|
|
|
|||
|
|
最近,有人通过提供一个去除了 GIL 的很有前途的概念验证 CPython 版本重新开始了讨论。这个概念验证的源代码可以在 [Github 这里](https://github.com/colesbury/nogil)找到。作者附上了一份[综合文件](https://docs.google.com/document/d/18CXhDb1ygxg-YXNBJNzfzZsDFosB5e6BfnXLlejd9l0/edit),解释了该操作的细节和特点。对于那些想更多了解这个主题的人来说,这是一本有趣的读物。
|