需要保护龙卷风中的全局变量?

时间:2016-03-03 00:52:23

标签: python-2.7 tornado

龙卷风在单线程中运行 在一个时间点,是否只有一个功能在运行? 所以我不需要锁定来保护变量? 甚至这些函数都是异步的吗?

2 个答案:

答案 0 :(得分:0)

龙卷风功能不间断运行,直到"产生"表达式(如果函数是协程)或函数返回。所以答案是否定的,你通常不需要使用Tornado应用程序中的锁来保护全局变量。

如果您只需要一个协程可以使用共享的全局变量,Python的标准线程.Lock是实现此目的的错误方法。 (实际上,在单线程Tornado应用程序中使用threading.Lock会导致死锁。)相反,使用tornado.locks.Lock来协调协同程序'访问。但这是一个高级用例,你几乎肯定不用担心。

有关背景,请阅读Glyph的着名" Unyielding"文章:

https://glyph.twistedmatrix.com/2014/02/unyielding.html

它是关于Twisted的,但通常适用于基于异步协同和回调的应用程序。

答案 1 :(得分:0)

如果在IOLoop中安排了两个或多个使用该变量的函数,则需要保护全局变量。例如。异步处理许多http请求。

您可以使用toro's Lock在龙卷风4.2+中,您可以使用tornado.locks,因为toro已合并到Tornado。

案例:

  • 有一个函数可以修改test_var并调用依赖函数,这需要更长的时间
  • 有清除test_var
  • 的功能

示例:

from tornado.ioloop import IOLoop
from tornado import gen
import time

test_var = 'test'

@gen.coroutine
def sleep():
    yield gen.Task(IOLoop.instance().add_timeout, time.time() + 0.1)

@gen.coroutine
def depend_on_test_var():
    yield sleep()
    print('depend_on_test %s' % test_var)

@gen.coroutine
def set_test_var():
    global test_var
    test_var = 'set'
    yield depend_on_test_var()

@gen.coroutine
def clear_test_var():
    global test_var
    test_var = 'clear'


@gen.coroutine
def main():
    print('main start %s' % test_var)
    yield [
        set_test_var(),
        clear_test_var()
    ]

IOLoop.instance().run_sync(main)

一次运行一个功能。由于非阻塞函数的yield(asynchttpclient,异步睡眠等)意味着做了其他事情直到完成,ioloop会采取下一个预定函数 - 这有点过度简化了。

当然这仅是示例,可以使用单独的yields

进行更改
@gen.coroutine
def main():
    print('main start %s' % test_var)
    yield set_test_var()
    yield clear_test_var()