2012-04-16 56 views
13

世界您好演示了瓶是:在Flask(WSGI)中使用全局單例,我是否必須擔心競爭條件?

from flask import Flask 
app = Flask(__name__) 

@app.route("/") 
def hello(): 
    return "Hello World!" 

if __name__ == "__main__": 
    app.run() 

如果我修改這個什麼像這樣:

from flask import Flask 
app = Flask(__name__) 

a = 1 
b = 2 
c = 3 

@app.route("/") 
def hello(): 
    a += 1 
    b += a 
    c += b 
    return "Hello World!" 

if __name__ == "__main__": 
    app.run() 

我明白WSGI應用程序可能有多個線程。 hello函數可以同時在多個線程上運行,然後我們會有競爭條件。它是否正確?如果上面的代碼不是線程安全的,我可以做些什麼來使線程安全?

避免全局性是一個可能的解決方案,但是你總是可以避免全局性?如果我想要一個像python對象緩存的東西呢?

回答

6

你可以使用鎖:

from threading import Lock 
from flask import Flask 
app = Flask(__name__) 

a = 1 
b = 2 
c = 3 
lock = Lock() 

@app.route("/") 
def hello(): 
    with lock: 
     a += 1 
     b += a 
     c += b 
    return "Hello World!" 

if __name__ == "__main__": 
    app.run() 
+3

你的榜樣(剪切和粘貼完全相同)返回給我一個500的,因爲被分配之前引用。 – jeremyjjbrown 2014-06-21 15:00:04

+0

這實際上並未回答所述問題。你需要鎖嗎?在什麼條件下?這僅適用於沒有GIL的口譯員嗎? – Basic 2016-12-23 23:20:06

0

你可能需要看看g對象,你可以從瓶中直接導入,保持了全球對象爲該請求。如果你使用的是事件驅動的WSGI服務器(龍捲風,gevent等),你應該沒有任何問題。

+4

我認爲'g'對象在請求期間只保持狀態,因此對於上面的用例沒有用處。 – osa 2015-01-21 23:52:53

2

你可以試試werkzeug的Local類。 這裏的一些信息看:Context Locals

例子:

from flask import Flask 
from werkzeug.local import Local 
app = Flask(__name__) 
loc = Local() 
loc.a = 1 
loc.b = 2 
loc.c = 3 

@app.route("/") 
def hello(): 
    loc.a += 1 
    loc.b += loc.a 
    loc.c += loc.b 
    return "Hello World!" 

if __name__ == "__main__": 
    app.run()