假设我有以下简单的课程:
import cherrypy
import os
class test:
test_member = 0;
def __init__(self):
return
def index(self):
self.test_member = self.test_member + 1
return str(self.test_member)
index.exposed = True
conf = os.path.join(os.path.dirname(__file__), 'config.ini')
if __name__ == '__main__':
# CherryPy always starts with app.root when trying to map request URIs
# to objects, so we need to mount a request handler root. A request
# to '/' will be mapped to HelloWorld().index().
cherrypy.config.update({'server.socket_host': '0.0.0.0'})
cherrypy.quickstart(test(), config=conf)
else:
# This branch is for the test suite; you can ignore it.
cherrypy.config.update({'server.socket_host': '0.0.0.0'})
cherrypy.tree.mount(test(), config=conf)
因此,当我第一次打开索引页时,我会返回 1,下一次会返回 2,然后是 3、4,依此类推。我的问题是:
我不完全理解 CherryPy 的线程是如何工作的,我想在这个简单的例子中我担心的是,在一个线程上 test_member 可能等于一件事,而当从另一个线程访问时,它会是完全不同的东西。如果我错过了一些有据可查的内容,我提前道歉,但一些谷歌搜索并没有真正找到我想要的东西。我知道对于这样一个简单的示例,有许多相对简单的路径可以解决这里的潜在问题(将变量的状态保留在数据库中,或类似的东西),但这在我的实际用例中不起作用.
存在丢失更新的危险。仅设置值不需要锁定,因为替换实例变量对于 GIL 来说是原子的(假设它不调用任何特殊方法等)。但是增加或使用更复杂的变量将需要不同的方案来使它们线程安全。
CherryPy 中的共享访问通常与任何其他 Python 程序没有什么不同。与其在这里对所有这些选项进行长篇大论,不如直接阅读 Python 中的线程同步机制 正如它所提到的,替换实例变量对于 GIL 来说可能是原子的,因此是线程安全的,但递增不是.
CherryPy 仅在相反方向添加一些助手:当您不想想要共享时:为每个请求/响应新创建(并正确销毁)
cherrypy.request
和cherrypy.response
对象 - 请随意坚持如果您只想在请求期间保留数据,请在 cherrypy.request.foo
中保存数据。