我在app.yaml中使用带有threadsafe: true
的Google App Engine 1.7.4上的Python 2.7运行时。
我有以下代码:
@ndb.tasklet
def fn_a(container):
''' access datastore and mutate container '''
@ndb.tasklet
def fn_b(container):
''' access datastore and mutate container '''
@ndb.toplevel
def parallel_fn():
shared_container = set()
yield fn_a(shared_container), fn_b(shared_container)
fn_a()
和fn_b()
访问和变异shared_container
并在parallel_fn()
中调用。 shared_container
是标准库set
,因此不是线程安全的。
我应该在适当的shared_container
标准库锁中包装threading
的mutator / accessor方法吗?
根据我对App Engine的理解,尽管设置了threadsafe: true
,但每个实例都是单线程的。因此,不需要使用threading
锁定对象?
初步测试显示不需要锁定,只会增加额外开销和死锁。它似乎也不应该做以下
if object not in shared_container:
yield any tasklet operation
shared_container.add(object)
shared_container
可能会在yield
操作期间由另一个执行行更新,因为object not in shared_container
语句可能无效。然而
if object not in shared_container:
shared_container.add(object)
yield any tasklet operation
绝对没问题。
答案 0 :(得分:3)
您不需要添加锁定代码,因为tasklet不在单独的线程中运行。在tasklet docs.
中了解相关信息如果设置threadsafe:true,GAE是多线程的。启动不同的线程来处理同一实例上的多个请求。通常这不是问题,因为您应该设计您的请求处理程序,以便能够在各种服务器实例上运行。
这并不适用于这个问题,但如果您真的测试线程问题,请小心。我不确定,但我认为在dev_appserver和生产GAE服务器上运行之间的线程行为是不同的,所以请确保在两者上进行测试。