5

我们正在 mod_wsgi 下推出我们的第一个 django 应用程序

`WSGIDaemonProcess our-appname processes=6 threads=15'`

我们正在讨论我们的 Python 代码以及它使用的 Redis 和 Postgres 库是否需要是线程安全的。

从阅读 mod_wsgi 文档中我可以看出,即使 apache worker 正在使用多个apache线程处理请求,我们的python代码也是单线程的。我在 mod_wsgi 文档上没有看到任何警告说“当心!您现在必须担心全局数据和线程安全!” 但也没有明确的“不要担心没有线程”。

我们没有在 Python 代码中明确使用线程做任何事情,在我们编写的任何内容中都没有提及它们。

但是这里的一些人认为,既然我们正在运行它threads=15,我们现在就处于多线程世界中。

谁能澄清这里到底发生了什么?我们的 Python 代码现在是否可以通过以前没有的相同数据执行多个线程?

4

3 回答 3

6

是的,显然您正在运行多线程应用程序,如果您不注意全局变量、类属性等,它将产生问题

如果您需要全局保存某些内容,请将其保存在线程本地存储中。

这是来自modwsgi 文档 Building_A_Portable_Application的引述

3. 应用程序必须是可重入的,或者简单地说,能够被多个线程同时调用。需要在请求的生命周期内存在的数据需要存储为基于堆栈的数据、线程本地数据或缓存在 WSGI 应用程序环境中。实际应用程序模块中的全局变量不能用于此目的。

所以我认为你已经被充分警告了。

于 2012-10-25T19:27:17.357 回答
1

python 解释器不是线程安全的,特别是因为引用计数,所以线程不能在同一个进程空间中同时访问 python 对象。您无法无意或有意地配置 mod_wsgi 来解决此问题,因为解释器受 GIL(全局解释器锁)保护。因此,您不必担心并发线程访问相同内存对象(内存锁定等)的风险带来的特别棘手的线程安全问题。

一些网络服务器(例如带有 gevent 支持者的 gunicorn)将同时在内存中拥有多个线程,因此无需在 I/O(数据库访问、网络访问等)上阻塞单个进程。mod_wsgi 也可能是这种情况。但是,这是以这样一种方式实现的,您不需要在应用程序代码中担心它——如果您的应用程序在多处理中使用是安全的,那么在这种有限的非并发线程中使用它也应该是安全的模型。

当然,您不能在应用程序运行时使用全局变量或动态编辑应用程序的某些部分,但是如果您在 Django 中执行类似的操作,那么您甚至在不必担心线程之前就会遇到问题。Django 和其他 Web 框架的设计使得数据作为请求传入和作为响应传出,而不必担心该模型中的线程/进程安全性。

对于任何 Web 应用程序,您确实需要担心对数据存储(尤其是数据库条目)的并发访问。在数据库访问方面进行防御性代码。

于 2012-10-25T19:59:56.087 回答
1

我认为安德鲁的回答有点误导。CPython(请注意还有其他 Python 实现,例如 Jython 和 PyPy)具有 GIL 的事实并不意味着您不必担心您的代码是线程安全的!由于 GIL,一个进程中的两个线程不能同时处于活动状态。但是并行性是通过定期在线程之间切换来模拟的。在程序执行期间,这种上下文切换可能随时发生。例如,如果您有一个foo包含“全局”变量的模块x,则以下方法可能会输出 2、3、4、... 中的任何内容,具体取决于执行相同方法的线程数:

def bar():
    foo.x = 1
    # a context switch might happen here!
    foo.x = foo.x + 1
    # or here!
    print(foo.x)

实际上,您可以将 mod_wsgi 配置为使用 max。1个线程。然后你不必担心线程安全。但是您的程序的正确性将取决于 Web 服务器的配置,这是一种非常不可取的情况。

于 2014-03-01T19:20:17.690 回答