为什么我必须担心 CPython 中的线程安全?

Why Do I have to worry about Thread Safety in CPython?

据我了解,全局解释器锁只允许单个线程访问解释器并执行字节码。如果是这样,那么在任何给定时间,只有一个线程会使用解释器及其内存。

因此我认为排除出现竞争情况的可能性是公平的,因为没有两个线程可以同时访问解释器的内存,但我仍然看到有关确保数据结构的警告 "thread safe".它有可能涵盖 python 解释器(如 cython)的所有实现,可以关闭 GIL 并允许真正的多线程。

我理解线程安全在没有启用 GIL 的解释器环境中的重要性。但是,对于 CPython,为什么在编写多线程 python 代码时鼓励线程安全?在 CPython 环境中会发生什么更糟糕的情况?

当然,竞争条件仍然会发生,因为对数据结构的访问不是原子的

假设您测试字典中是否存在某个键,然后执行一些操作来添加该键:

if key not in dictionary:
    # calculate new value
    value = elaborate_calculation()
    dictionary[key] = value

线程可以在not in测试返回true后随时切换,另一个线程也会得出密钥不是的结论那里。现在有两个线程在做计算,你不知道哪一个会赢。

GIL 所做的只是保护 Python 的 内部解释器状态 。这并不意味着 Python 代码本身使用的数据结构现在已被锁定和保护。

重要说明:尽管有 GIL,Python 中的多处理模块在某种程度上是同步的,因为对同一变量的访问可以同时发生在不同的进程中。

这可能会破坏您的数据,或者至少会破坏您的控制流,这就是推荐线程安全的原因。

至于为什么会发生这种情况,尽管只有一个解释器,但没有任何东西可以阻止(至少据我所知)两个预解释的代码片段同步访问共享内存的相同部分。做的时候说:

import multiprocessing
def my_func ():
    print("hello world")
my_process=multiprocessing.Process (target=my_func, args=(,))
my_process.start ()
my_process.join ()

我的理解是,解释(在这种情况下)所花费的时间 my_func 被埋没在生成新进程所花费的开销中。

在这种情况下,术语"process"在这里更合适,因为有临时产生的工作线程只是为了复制数据,所以正在进行一些数据握手,所以实际上相当多与传统线程的生成不同的过程(双关语)。

希望对您有所帮助。