Flask 靠什么保证两个同时进来的请求看到的是各自的 request 和 g?线程、协程、线程池分别怎么样?这篇用 ContextVar、threading.local 和真实的 gunicorn 并发请求逐个验证。
新线程里 cv.get(): 默认值 | 把 copy_context() 带进线程用 ctx.run: 主线程设的值 Python 版本 3.14.7 | sys.flags.thread_inherit_context = 0
任务A 睡醒后读到 任务A 设的值 任务B 睡醒后读到 任务B 设的值 任务C 睡醒后读到 任务C 设的值 gather 结束后 main 里 cv.get() = main 设的值
threading.local: ['X 睡醒后读到 Z', 'Y 睡醒后读到 Z', 'Z 睡醒后读到 Z'] ContextVar : ['X 睡醒后读到 X', 'Y 睡醒后读到 Y', 'Z 睡醒后读到 Z']
3 个线程各自读到: ['线程0', '线程1', '线程2'] | 3 个协程各自读到: ['任务0', '任务1', '任务2'] | 主线程读到: 主线程 Local 的内部存储: ContextVar (ContextVar) release_local(L) 之后访问 L.name: AttributeError: name
16 个并发请求(单 worker、8 线程)总耗时 481 ms;g 里读回来的值与自己的参数不一致的请求数:0;示例:['0|0|thread-ok', '1|1|thread-ok', '2|2|thread-ok']
直接 submit: RuntimeError copy_current_request_context: / copy_context().run: /