在多线程Web服务器上使用python + wsgi:这是竞争条件吗?

7 投票
2 回答
2335 浏览
提问于 2025-04-18 06:41

假设我写了一个 wsgi application 应用程序。我在 Linux 上的 Apache2 服务器上运行这个应用,并且使用了多线程的 mod-wsgi 配置,这样我的应用就可以在一个进程中运行多个线程:

WSGIDaemonProcess mysite processes=3 threads=2 display-name=mod_wsgi
WSGIProcessGroup mysite
WSGIScriptAlias / /some/path/wsgi.py

应用代码是:

def application(environ, start_response):
    from foo import racer
    status = '200 OK'
    response_headers = [('Content-type', 'text/plain')]
    start_response(status, response_headers)
    return [racer()] #call to racer creates a race condition?

模块 foo.py:

a = 1
def racer():
    global a
    a = a + 1
    return str(a)

我是不是在变量 a 上创建了一个竞争条件?我猜 a 是一个模块级别的变量,存在于 foo.py 中,并且在多个线程之间是共享的?

由此引申出更多理论问题:

  1. 在同一个进程内并发的线程访问和修改同一个 a 变量,所以我的例子不是线程安全的吗?
  2. 如果我的网络服务器是 Apache,那么在 Linux 上我的应用的每个线程都是通过 C 级别的 pthreads API 创建的,而 pthread 必须执行的函数是某种 Python 解释器的主函数吗?还是说 Apache 在某种程度上保护我免受这个错误的影响?
  3. 如果我在一个用 Python 写的网络服务器上运行,比如 TornadoHTTPServer,那么这个用 Python 写的服务器是通过 Python 级别的 threading.Thread 对象来实现线程的,并在每个线程中运行 application 函数。那么,我想这也是一个竞争条件吗?(我还想,在这种情况下,我可以忽略底层的 C 级别 pthreads 实现,只关注 Python 函数,因为解释器不会让我修改 C 级别的共享数据,从而影响其功能。所以,打破线程安全的唯一方法就是处理全局变量吗?这样理解对吗?)

2 个回答

暂无回答

撰写回答