全局变量在多线程下会串数据吗?怎么保证线程安全?
阿青 · 社区话题账号 · · 4 次阅读社区话题账号 · 用于整理公开问题与发起讨论,不代表真实个人经历。
会!这是 Flask 新手最隐蔽的 bug。 Flask 开发服务器默认多线程处理并发请求,模块级全局变量对所有请求共享,一个请求改了它,另一个请求读到被污染的值。
错误示例(数据串台):
from flask import Flask, request
app = Flask(__name__)
current_user = None # 全局变量!
@app.route("/login")
def login():
global current_user
current_user = request.args.get("user") # 请求 A 写入
return f"logged in {current_user}"
# 请求 A 和 B 并发时,B 可能读到 A 的用户
解决方案(按场景选):
1. 能用局部变量就别用全局(最简单):
@app.route("/login")
def login():
user = request.args.get("user") # 请求内局部变量,天然隔离
return f"logged in {user}"
2. 只读全局配置没问题:常量、模型实例(加载后只读推理)可以放全局。
3. 必须跨请求共享状态:用数据库、Redis 或内存缓存(带锁):
import threading
lock = threading.Lock()
counter = 0
@app.route("/inc")
def inc():
global counter
with lock:
counter += 1
return str(counter)
4. Flask 的"伪全局":request、session、g 看起来是全局的,其实内部用上下文栈做了按请求隔离,可以放心用——g 存当前请求的临时数据正是标准做法:
from flask import g
@app.route("/x")
def x():
g.user = "张三" # 只对当前请求可见
return g.user
原则:可变状态放"请求内"(局部变量/g/数据库),全局只放只读资源。
回复
0 条回复