讲师中心 微信公众号

工具推荐

视频效率加速
AniShort
AniShort

AI短剧协同制作平台

updream

一键生成高质量推广成片

立刻MV
立刻MV

低成本歌曲 MV、视频生成

Seko
Seko

AI短剧一键生成成片

Python asyncio.Lock 的可重入性分析

落伟大大_5154

落伟大大_5154

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

|

331人浏览过

|

来源于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.Lock 的 locked() 方法只告诉你当前是否被占用,不告诉你是谁占的、占了几次

为什么 asyncio 没内置 ReentrantLock

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

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

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

Python Hardener
Python Hardener

通过完整的安全审查、代码整洁重构、健壮的错误处理、正确的日志记录以及完整的文档字符串覆盖,强化 Python 脚本。

下载
  • 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工具

更多
二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

创客贴AI

创客贴AI是一款AI图像与设计工具,AI辅助的智能在线设计工具。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

码上飞
码上飞 Hot

一款基于自然语言的AI应用开发平台,可根据用户描述自动生成应用程序,帮助个人和团队快速完成应用原型与开发。

相关专题

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

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

4758

2023.08.10

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

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

1329

2025.12.24

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

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

443

2026.01.21

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

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

599

2026.01.21

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

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

449

2026.02.06

C++多线程并发控制与线程安全设计实践
C++多线程并发控制与线程安全设计实践

本专题围绕 C++ 在高性能系统开发中的并发控制技术展开,系统讲解多线程编程模型与线程安全设计方法。内容包括互斥锁、读写锁、条件变量、原子操作以及线程池实现机制,同时结合实际案例分析并发竞争、死锁避免与性能优化策略。通过实践讲解,帮助开发者掌握构建稳定高效并发系统的关键技术。

273

2026.03.16

Java 多线程与并发编程实战
Java 多线程与并发编程实战

深入讲解 Java 并发编程体系,涵盖 Thread / Runnable / Callable 线程创建方式、线程生命周期与状态转换、synchronized 同步锁与 Lock/ReentrantLock 显式锁、volatile 可见性保证、ThreadPool 线程池配置与调优(核心参数/拒绝策略)、JUC 并发工具类(CountDownLatch/CyclicBarrier/Semaphore/ConcurrentHashMa

389

2026.04.17

C++ 多线程使用教程大全
C++ 多线程使用教程大全

系统讲解 C++11 及后续标准引入的多线程编程能力,涵盖 std::thread 线程创建与生命周期管理、std::mutex / shared_mutex 互斥锁与读写锁、std::condition_variable 条件变量同步、std::atomic 原子操作与内存序(memory_order)、std::future / promise / async 异步任务、线程池的设计与实现、死锁检测与避免策略,帮助开发者编写正确高效

256

2026.04.28

Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

60

2026.11.06

热门下载

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

精品课程

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn