python + wsgi上多
假设我写了一个wsgi application
。 我在Linux
使用多线程mod-wsgi
配置在Apache2
上运行此应用程序,以便我的应用程序在每个进程的多个线程中运行:
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
并且在线程之间是相同的(共享)?
更多的理论问题来源于此:
a
变量,所以我的例子不是线程安全的? Apache
,我的Linux应用程序的每个线程都是在C层上用pthreads
API和函数创建的, pthread
必须执行的函数是某种python解释器的主函数? 或者Apache保护我不知何故从这个错误? Tornado
的HTTPServer
这样的python写的网络服务器上运行它,该怎么办? 用python编写的Web服务器将线程实现为python级别的threading.Thread
对象,并在每个线程中运行application
函数。 那么,我认为这是一个竞争条件? (我也假设,在这种情况下,我可以从threading.Thread
实现中抽象出底层的C层pthreads
,并且只考虑python函数,因为解释器不会允许我修改C层共享数据并解决它的功能。解决线程安全问题的唯一方法是处理全局变量?是吗?) 是的,你在那里有一个竞赛条件,但它与进口无关。 foo.a
的全局状态受到a + 1
和a = ...
之间a + 1
数据竞争; 因为两个线程可以看到相同的值a
,并由此计算出相同的继任者。
导入机制本身通过一个进程锁来防止多线程重复导入(参见imp.lock_held()
)。 尽管理论上这可能导致死锁,但几乎从不会发生这种情况,因为很少有python模块在导入时锁定其他资源。
这也表明,可以sys.path
修改sys.path
; 因为这通常只在导入时发生(为了进一步导入),并且线程已经保存了导入锁定,所以其他线程不会导致也会修改该状态的导入。
尽管如此,在racer()
修改比赛非常容易:
import threading
a = 1
a_lock = threading.Lock()
def racer():
global a
with a_lock:
my_a = a = a + 1
return str(my_a)
这将是您控制中的任何全局,可变状态所需要的。
阅读关于各种进程/线程配置的mod_wsgi文档,特别是关于数据共享的内容。
特别是它说:
在仍然使用子进程本地模块中的全局数据(例如作为缓存)的情况下,全局数据的访问和修改必须由本地线程锁定机制来保护。
链接地址: http://www.djcxy.com/p/86485.html