0

0

Python并发常见陷阱_死锁与竞态条件分析

舞夢輝影

舞夢輝影

发布时间:2026-03-02 15:47:28

|

649人浏览过

|

来源于php中文网

原创

死锁是多个线程因锁获取顺序不一致导致的循环等待,竞态条件是共享状态未受保护而依赖执行时序;二者均需通过统一锁序、原子操作封装、显式同步机制及运行时检测来防范。

python并发常见陷阱_死锁与竞态条件分析

Python并发编程中,死锁和竞态条件是最易被低估、却最常导致线上故障的两类问题。它们不总在测试中暴露,却可能在高并发、特定时序下突然引发数据错乱、服务卡死或响应超时。

死锁:多个线程互相等待对方释放锁

死锁不是“锁用多了”,而是锁的获取顺序不一致导致的循环等待。典型场景是两个线程分别持有A锁、B锁,又同时试图获取对方持有的锁。

例如:

线程1执行:lock_a.acquire() → lock_b.acquire()
线程2执行:lock_b.acquire() → lock_a.acquire()
一旦线程1拿到lock_a、线程2拿到lock_b,二者都会阻塞在第二步,永远无法继续。

避免方法:

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

  • 始终按**全局统一顺序**获取多个锁(如按锁对象id大小排序后依次acquire)
  • 使用threading.Locktimeout参数(如lock.acquire(timeout=2)),失败后主动释放已持锁并重试
  • 优先考虑threading.RLock(可重入锁)或更高层抽象,如queue.Queue——它内部已处理同步,无需手动加锁

竞态条件:共享状态未受保护,执行结果依赖时序

竞态不是“多线程一定出错”,而是当读-改-写操作(如counter += 1)未原子化时,多个线程可能同时读到旧值、各自+1、再写回,导致一次更新丢失。

Favird No-Code Tools
Favird No-Code Tools

无代码工具的聚合器

下载

常见误判:

  • 认为局部变量或函数内对象不会竞态(错误:若该对象被多个线程共享引用,仍会)
  • 只给写操作加锁,忽略读操作也可能需要同步(尤其涉及复合判断,如if not data: data = init()
  • list.append()等看似“简单”的操作代替锁(虽CPython中部分操作是原子的,但不保证逻辑原子性,且跨版本/解释器不可靠)

安全做法:

  • 识别所有**跨线程共享的可变对象**(包括模块级变量、类属性、传入的可变参数)
  • 对读-改-写操作,用锁包裹整个逻辑段,而非仅包裹赋值语句
  • threading.local()为每个线程提供独立副本,避免共享(适合配置、上下文等场景)

asyncio中的特殊陷阱:await不是线程安全的“保险丝”

协程并发不等于无锁。虽然asyncio是单线程事件循环,但以下情况仍会触发竞态:

  • 多个协程修改同一全局变量或对象属性(如shared_dict['count'] += 1
  • await前后状态不一致(如检查资源存在→await IO→资源被其他协程删除)
  • 误以为asyncio.Lock能保护所有异步操作——它只阻塞协程调度,不阻止CPU密集型任务打断

建议:

  • 对共享状态,显式使用asyncio.Lock,且确保await lock.acquire()lock.release()成对出现(推荐用async with lock:
  • 避免在协程中直接操作线程共享对象;如需与线程交互,用loop.run_in_executor()并做好同步
  • asyncio.create_task()替代await来实现真正的并发协作,而非串行等待

调试与检测:别等线上崩了才找问题

死锁和竞态往往难以复现。提前介入更有效:

  • threading.settrace()sys.settrace()记录锁获取/释放轨迹(测试环境可用)
  • 启用threading.Thread(daemon=True)前确认无关键锁未释放,否则主线程退出可能留下死锁残留
  • 使用pytest-asyncio配合asyncio.wait_for()设置超时,快速暴露挂起协程
  • 对关键计数器、状态机,增加运行时断言(如assert counter >= 0)或校验钩子

热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

通义千问
通义千问

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

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

更多
if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

839

2023.08.22

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

201

2023.11.20

全局变量怎么定义
全局变量怎么定义

本专题整合了全局变量相关内容,阅读专题下面的文章了解更多详细内容。

87

2025.09.18

python 全局变量
python 全局变量

本专题整合了python中全局变量定义相关教程,阅读专题下面的文章了解更多详细内容。

103

2025.09.18

线程和进程的区别
线程和进程的区别

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

723

2023.08.10

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

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

372

2025.12.24

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

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

27

2026.01.21

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

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

25

2026.01.21

Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

45

2026.02.28

热门下载

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

精品课程

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

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 4.7万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.8万人学习

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

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