Python CherryPy、线程和成员变量;潜在问题?
假设我有以下简单的类:Python CherryPy、线程和成员变量;潜在问题?,python,threadpool,cherrypy,Python,Threadpool,Cherrypy,假设我有以下简单的类: 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
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_成员可能等于一个东西,而从另一个线程访问时,它将是完全不同的东西。如果我错过了一些有详细记录的东西,我会提前道歉,但是一些谷歌搜索并没有真正找到我想要的东西。我知道对于这样一个简单的例子,有许多相对简单的方法可以解决这里的潜在问题(将变量的状态保存在数据库中,或者沿着这些路线),但这在我的实际用例中不起作用。有丢失更新的危险。仅仅设置值不需要锁定,因为替换实例变量对于GIL来说是原子的(假设它不调用任何特殊方法等)。但递增或使用更复杂的变量将需要不同的方案使其线程安全 CherryPy中的共享访问通常与任何其他Python程序没有什么不同。与其在这里对所有这些选项进行长时间的重复,不如像上面提到的那样指导您,替换实例变量对于GIL来说可能是原子的,因此是线程安全的,但递增不是
CherryPy只在相反方向添加了一些帮助程序:当您不想共享时:
CherryPy.request
和CherryPy.response
对象是新创建的(并正确销毁)对于每个请求/响应——如果您只想在请求期间保留数据,请随时将数据粘贴到cherrypy.request.foo
。有丢失更新的危险。仅仅设置值不需要锁定,因为替换实例变量对于GIL来说是原子的(假设它不调用任何特殊方法等)。但递增或使用更复杂的变量将需要不同的方案使其线程安全
CherryPy中的共享访问通常与任何其他Python程序没有什么不同。与其在这里对所有这些选项进行长时间的重复,不如像上面提到的那样指导您,替换实例变量对于GIL来说可能是原子的,因此是线程安全的,但递增不是
CherryPy只在相反方向添加了一些帮助程序:当您不想共享时:
CherryPy.request
和CherryPy.response
对象是新创建的(并正确销毁)对于每个请求/响应——如果您只想在请求期间保留数据,请在cherrypy.request.foo
中随意粘贴数据。我想您的意思是:self.test_member=self.test_member+1?@fumanchu-我愿意,对此表示歉意。现在修好了。我想你的意思是:self.test_member=self.test_member+1?@fumanchu-我知道,为此道歉。现已修复。但是,self.member=self.member+1
不是线程安全的,因为读取可以交错。@nneonneo的交错是指(假设self.member从0开始):(1)线程1读取self.member(2)线程2读取self.member(3)线程2将self.member设置为1(4)线程1也将self.member设置为1?@fumanchu-看起来该链接包含了很多我想要的东西。感谢您提供的信息。@repole:是的。之所以会发生这种交错,是因为在Python中获取变量、添加变量和设置变量都是单独的字节码操作。@nneonneo啊,是的,谢谢。我想“INPLACE\u ADD只是一个op”,但它当然与LOAD\u ATTR和STORE\u ATTR分开。捕捉得很好。但是,self.member=self.member+1
不是线程安全的,因为读取可以交错。@nneonneo的交错是指(假设self.member从0开始):(1)线程1读取self.member(2)线程2读取self.member(3)线程2将self.member设置为1(4)线程1也将self.member设置为1?@fumanchu-看起来该链接包含了很多我想要的东西。感谢您提供的信息。@repole:是的。之所以会发生这种交错,是因为在Python中获取变量、添加变量和设置变量都是单独的字节码操作。@nneonneo啊,是的,谢谢。我想“INPLACE\u ADD只是一个op”,但它当然与LOAD\u ATTR和STORE\u ATTR分开。抢手货