Flask默认是单线程吗?

首先环境为python3.6.8
Flask 版本 2.0.3
Flask-SQLAlchemy 版本 2.5.1

在网上查找Flask资料的时候,经常看到有flask默认是单线程的观点,我也一直信以为真,但是最近做的一个项目使用到了redis的互斥锁,大概业务逻辑是如果缓存中没有拿到数据,就会先去尝试拿到互斥锁,然后再进行缓存的重建,重建完后就会释放互斥锁,但是我在这个过程中发现,互斥锁被多次尝试拿取且拿取失败。

# 尝试加锁
def tryLock(key):
    flag = Redis.setnx(key, 1)
    print(flag,end=' ')
    if flag:
        Redis.expire(key, 10)
        return True
    return False
# 释放锁
def unLock(key):
    return Redis.delete(key)

使用jmeter并发访问网站5s,访问2000次输出为

True False False False ....

但是问题是Flask不是单线程的吗,如果是单线程的话,锁资源只有被释放,上一个请求完成,我们的其他请求才能拿到锁资源
这样的话拿取锁资源一定会成功呀,为什么会失败呢?

所以,我开始尝试去查看Flask的源码,发现其实flask应该是从1.0版本之后就已经默认是多线程了

... versionchanged:: 1.0
    If installed, python-dotenv will be used to load environment
    variables from :file:`.env` and :file:`.flaskenv` files.

    If set, the :envvar:`FLASK_ENV` and :envvar:`FLASK_DEBUG`
    environment variables will override :attr:`env` and
    :attr:`debug`.

    Threaded mode is enabled by default.

这是源码的注释,主要看最后一句
然后再往下看发现

options.setdefault("use_reloader", self.debug)
options.setdefault("use_debugger", self.debug)
options.setdefault("threaded", True)

最后一段代码则确定了我的猜想,确实默认是多线程。
后面看到了这段源码

try:
    run_simple(t.cast(str, host), port, self, **options)
finally:
    self._got_first_request = False

发现调用了run_simple,而run_simple其实是werkzeug启动的方法,其中是多线程默认是没有开启的。

因此得出结论,Flask的app.run方法封装了werkzeug的run_simple方法,在1.0版本之后就默认使用多线程了。

最后测试换成单线程后,果然就没有出现False了,且多线程的开启和DEBUG的开启也没有关系(看到有文章说有关系)。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值