web-dev-qa-db-ja.com

Flask(WSGI)でグローバルシングルトンを使用する場合、競合状態について心配する必要がありますか?

FlaskのHelloWorldデモは次のとおりです。

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オブジェクトキャッシュのようなものが必要な場合はどうなりますか?

21
Buttons840

あなたはロックを使うことができます:

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()
11
Martin Blech

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()
2
Florentin