Python全局变量是否线程安全?

5

编辑:我想知道在像龙卷风这样的单线程Web框架中,全局变量是否安全。

我正在使用mongoengine orm,它从全局变量获取数据库连接:

_get_db() # gets the db connection

我同时使用tornado,这是一个单线程的python web框架。在一个特定的视图中,我需要获取一个数据库连接并解引用一个DBRef对象[类似于外键]:

# dereference a DBRef
_get_db().dereference(some_db_ref)

_get_db返回的连接是全局变量,是否存在冲突的可能性,导致错误的值返回给错误的线程?


似乎这与特定库有关,而不是全局变量。 - Roger Pate
MongoDB是否指定_get_db是线程安全的? - Skurmedel
4个回答

3

在与Python对象交互时,线程始终需要持有GIL。保存变量的命名空间是一个Python对象(frameobject或dict,具体取决于变量类型)。在多个线程中获取或设置变量总是安全的,您永远不会得到垃圾数据。

然而,通常的竞态条件仍适用于获取的对象或在分配时替换的对象。像x += 1这样的语句是线程安全的,因为不同的线程可以在获取和存储之间运行,改变x的值,然后您会覆盖它。


你是在说任何带有 x += 1 的函数或类方法都不是线程安全的吗? - Carson
他说,在Python线程中设置全局变量可能会失败 - 另一个线程可以在此后将变量设置为不同的值。如果您依赖于在代码块期间设置该值,则应使用锁定。它是线程安全的,因为您不会得到seg-faults,但并不意味着您可能会得到意外的值。循环列表和字典是经典的例子,您可能会遇到麻烦 - 例如,字典键可能会意外消失。 - drevicko

2
假设MongoEngine正在包装PyMongo(我相信是这样),那么您应该没问题。PyMongo完全支持线程安全。

是的,它包装了pymongo,但将pymongo.Connection实例存储在全局变量中。 - Carson
那就好,可以安全地共享一个连接实例。 - mdirolf

1

不是的,但在Python中使用锁非常简单。使用try: finally:模式确保在修改全局变量后释放锁。


0

全局变量与其他变量相比,并没有使它们更或者更少线程安全的特性。无论操作是否可能在不同的线程中失败或返回不正确的结果,最佳实践是您应该保护在线程之间共享的数据。

如果我理解你的意思,你正在询问一个变量在单线程环境中是否安全。在这种情况下,当数据在并发进程之间共享时,该变量是安全的(毕竟,没有其他运行的东西可能会中断它)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接