0

0

Python asyncio.Lock 的可重入性分析

冷漠man

冷漠man

发布时间:2026-02-14 18:41:07

|

311人浏览过

|

来源于php中文网

原创

asyncio.lock 不可重入,重复acquire会导致死锁;它不记录持有者、不计数,设计上仅支持“谁获取谁释放”;需可重入时应拆分临界区或用semaphore+手动状态管理,而非模拟rlock。

python asyncio.lock 的可重入性分析

asyncio.Lock 不支持可重入

它和 threading.Lock 一样,不是可重入的:同一个协程重复调用 acquire() 会死锁。这不是 bug,是设计如此——asyncio.Lock 的语义就是“谁拿到谁释放”,不记录持有者身份,也不计数。

常见错误现象:RuntimeWarning: coroutine 'Lock.acquire' was never awaited(忘了 await),或者更隐蔽的:协程卡在第二次 await lock.acquire(),整个 task 再无响应。

  • 如果你需要“同一线程/协程能多次进入”,必须换用 asyncio.Semaphore(1) + 手动计数,或改用第三方库如 asyncio-ext 中的 ReentrantLock
  • 别试图靠 try/finally + 标志位模拟可重入——协程切换会让标志位失效,状态不同步
  • asyncio.Locklocked() 方法只告诉你当前是否被占用,不告诉你是谁占的、占了几次

为什么 asyncio 没内置 ReentrantLock

因为可重入在异步上下文里意义模糊:协程调度不可预测,“同一线程”概念不存在;一个协程中途被挂起,另一个协程可能已持锁,此时“重入”就变成了跨协程竞争,反而破坏语义一致性。

典型使用场景误用:async def inner(): await lock.acquire()async def outer(): await lock.acquire(); await inner() 调用——表面像递归,实则两个独立 await 点,lock 已被释放或未释放都不可控。

立即学习Python免费学习笔记(深入)”;

西安网上购物网店系统
西安网上购物网店系统

西安网上购物网店系统的主要亮点:(1)商品的分类更加细化和明朗,可以三级分类,价格可以多层次\多级别,按照后台设置的,吸引会员加入。(2)会员和非会员购物并存,订单直接支付和会员帐户支付并存,电话支付与网上支付多种支付方式。(3)自定义商品扩展属性,多种扩展属性定义模式,强大的商品管理功能,多重分类功能(4)灵活的会员积分系统,灵活的会员权限控制,模版丰富多彩,模版代码分离,方便修改模版(5)支付

下载
  • Python 的 threading.RLock 依赖线程标识(threading.get_ident()),而 asyncio 没有“协程标识”这种稳定机制
  • 即便实现 RLock,也无法保证 await 点之间的执行连续性,容易引发逻辑错乱
  • 官方明确表示:不计划加入 asyncio.ReentrantLock,推荐拆分临界区或用更高层抽象(如 asyncio.Queue

替代方案的实际写法与坑

最轻量的可行替代是用 asyncio.Semaphore 配合协程局部状态,但要注意:它本身也不可重入,只是更容易封装。

简短示例(不推荐生产直接用,仅说明思路):

class SimpleReentrantLock:
    def __init__(self):
        self._sem = asyncio.Semaphore(1)
        self._owner = None
        self._count = 0

    async def acquire(self):
        cur_task = asyncio.current_task()
        if self._owner is cur_task:
            self._count += 1
            return True
        await self._sem.acquire()
        self._owner = cur_task
        self._count = 1
        return True

    def release(self):
        if self._owner is not asyncio.current_task():
            raise RuntimeError("Cannot release un-acquired lock")
        self._count -= 1
        if self._count == 0:
            self._owner = None
            self._sem.release()
  • 这个类在单任务内能工作,但无法处理 cancel、timeout 或嵌套中混入其他协程的情况
  • asyncio.current_task() 在 Python 3.7+ 可用,3.6 需用 asyncio.Task.current_task()(已弃用)
  • 真正健壮的方案是避免重入需求:把大临界区拆成多个小锁,或用消息队列串行化操作

asyncio.Lock 和 threading.Lock 混用的陷阱

绝对不要在同一个资源上混用两者。比如用 threading.Lock 保护一个变量,又在 async 函数里用 asyncio.Lock 去“保护同一段逻辑”——它们互不感知,完全无效。

常见错误场景:多线程运行 asyncio event loop(如 loop.run_in_executor),然后在 executor 里误用 asyncio.Lock(它只能在协程中 await,不能在同步线程里调用)。

  • asyncio.Lock.acquire() 是协程函数,必须 await;在普通线程里直接调用只会返回 coroutine 对象,不阻塞也不生效
  • 跨线程共享状态,该用 threading.Lock + loop.call_soon_threadsafe() 通知事件循环,而不是幻想 asyncio 同步原语能穿透线程边界
  • 所有 asyncio.* 同步原语都只对“同一个 event loop 内的协程”有效,这是根本边界
实际用的时候,最常被忽略的是:你以为的“重入”,往往暴露的是临界区划分不合理。与其花力气绕过限制,不如重新审视——这段逻辑真需要锁?能不能用不可变数据、原子更新、或队列通信替代?

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

673

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

325

2025.12.24

java多线程相关教程合集
java多线程相关教程合集

本专题整合了java多线程相关教程,阅读专题下面的文章了解更多详细内容。

24

2026.01.21

C++多线程相关合集
C++多线程相关合集

本专题整合了C++多线程相关教程,阅读专题下面的的文章了解更多详细内容。

24

2026.01.21

C# 多线程与异步编程
C# 多线程与异步编程

本专题深入讲解 C# 中多线程与异步编程的核心概念与实战技巧,包括线程池管理、Task 类的使用、async/await 异步编程模式、并发控制与线程同步、死锁与竞态条件的解决方案。通过实际项目,帮助开发者掌握 如何在 C# 中构建高并发、低延迟的异步系统,提升应用性能和响应速度。

94

2026.02.06

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

77

2026.02.13

微博网页版主页入口与登录指南_官方网页端快速访问方法
微博网页版主页入口与登录指南_官方网页端快速访问方法

本专题系统整理微博网页版官方入口及网页端登录方式,涵盖首页直达地址、账号登录流程与常见访问问题说明,帮助用户快速找到微博官网主页,实现便捷、安全的网页端登录与内容浏览体验。

49

2026.02.13

Flutter跨平台开发与状态管理实战
Flutter跨平台开发与状态管理实战

本专题围绕Flutter框架展开,系统讲解跨平台UI构建原理与状态管理方案。内容涵盖Widget生命周期、路由管理、Provider与Bloc状态管理模式、网络请求封装及性能优化技巧。通过实战项目演示,帮助开发者构建流畅、可维护的跨平台移动应用。

21

2026.02.13

TypeScript工程化开发与Vite构建优化实践
TypeScript工程化开发与Vite构建优化实践

本专题面向前端开发者,深入讲解 TypeScript 类型系统与大型项目结构设计方法,并结合 Vite 构建工具优化前端工程化流程。内容包括模块化设计、类型声明管理、代码分割、热更新原理以及构建性能调优。通过完整项目示例,帮助开发者提升代码可维护性与开发效率。

10

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.4万人学习

Django 教程
Django 教程

共28课时 | 4.3万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号