新闻中心
python多线程中的死锁和递归锁用法
死锁是多线程竞争资源时因循环等待导致程序卡住的现象,如线程A持lock1等lock2、B持lock2等lock1;避免方法是统一加锁顺序并使用RLock支持同线程重复加锁,防止自我阻塞。

在Python多线程编程中,死锁(Deadlock)是一个常见且棘手的问题。它通常发生在多个线程竞争多个锁资源时,彼此相互等待对方释放锁,导致所有线程都无法继续执行。
什么是死锁?
假设有两个线程 A 和 B,以及两把锁 lock1 和 lock2:
- 线程 A 持有 lock1,并试图获取 lock2
- 线程 B 持有 lock2,并试图获取 lock1
这时,A 等 B 释放 lock2,B 等 A 释放 lock1,形成循环等待,程序卡住——这就是典型的死锁。
示例:产生死锁的代码
import threading
import time
<p>lock1 = threading.Lock()
lock2 = threading.Lock()</p><p>def thread_1():
with lock1:
print("线程1 获取了 lock1")
time.sleep(1)
print("线程1 尝试获取 lock2")
with lock2:
print("线程1 获取了 lock2")</p><p>def thread_2():
with lock2:
print("线程2 获取了 lock2")
time.sleep(1)
print("线程2 尝试获取 lock1")
with lock1:
print("线程2 获取了 lock1")</p><p>t1 = threading.Thread(target=thread_1)
t2 = threading.Thread(target=thread_2)</p><p>t1.start()
t2.start()</p><p>t1.join()
t2.join()
运行这段代码,大概率会卡住,出现死锁。
如何避免死锁?使用递归锁 RLock
虽然 RLock(可重入锁)不能直接解决多锁交叉导致的死锁,但它允许同一个线程多次获取同一把锁,防止因重复加锁导致的自我阻塞。
更重要的是,避免死锁的关键是:保持加锁顺序一致。
Narration Box
Narration Box是一种语音生成服务,用户可以创建画外音、旁白、有声读物、音频页面、播客等
68
查看详情
改进方案:统一加锁顺序 + 使用 RLock 防止重复加锁问题
import threading
import time
<h1>使用 RLock 替代 Lock,支持同一线程重复进入</h1><p>lock1 = threading.RLock()
lock2 = threading.RLock()</p><p>def worker_1():
print("线程1 开始")
with lock1:
print("线程1 获取 lock1")
time.sleep(0.5)
with lock2: # 统一先 lock1 再 lock2
print("线程1 获取 lock2")</p><p>def worker_2():
print("线程2 开始")
with lock1: # 同样先获取 lock1
print("线程2 获取 lock1")
time.sleep(0.5)
with lock2:
print("线程2 获取 lock2")</p&g
t;<p>t1 = threading.Thread(target=worker_1)
t2 = threading.Thread(target=worker_2)</p><p>t1.start()
t2.start()</p><p>t1.join()
t2.join()
这个版本中,两个线程都按照 lock1 → lock2 的顺序加锁,避免了循环等待,从而防止死锁。
递归锁 RLock 的典型用途
当一个函数在持有锁的情况下调用另一个也需要同一把锁的函数时,普通 Lock 会导致阻塞,而 RLock 允许这种情况。
import threading
<p>rlock = threading.RLock()</p><p>def func1():
with rlock:
print("func1 已加锁")
func2() # 调用另一个需要同样锁的函数</p><p>def func2():
with rlock: # 同一线程可再次获取锁
print("func2 也获得了锁")</p><p>t = threading.Thread(target=func1)
t.start()
t.join()
如果这里用的是 Lock(),程序会在进入 func2 时被自己阻塞。
总结建议
- 死锁主因是锁的获取顺序不一致或循环等待
- 使用 threading.RLock 可解决同一线程重复加锁问题
- 避免死锁的根本方法是:始终以相同顺序获取多个锁
- 设计时尽量减少锁的数量和嵌套层级
- 可以使用超时机制(
acquire(timeout=))来检测潜在死锁
基本上就这些。掌握锁的使用顺序和选择合适的锁类型,能有效避免多线程中的死锁问题。
以上就是python多线程中的死锁和递归锁用法的详细内容,更多请关注其它相关文章!
# 如何处理
# 莆田网站优化
# 旅游网站系统建设
# 百度霸屏推广一手营销吧TT团队
# seo优化的网站怎么用
# 阜新推广网站建设有用吗
# 东莞网站建设推广策划
# 越秀网站seo优化排名
# 云南seo运营团队排行
# 联盟网站推广
# 网站推广软件需要多少钱
# 是一个
# python
# 如何使用
# 数据处理
# 的是
# 多个
# 加锁
# 多线程
# 递归
# 死锁
# 有锁
# 一加
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
msn官网入口地址手机版 msn官方网站手机最新链接
限制HTML日期输入框的日期选择范围
PHP表单数据传递:如何通过隐藏输入字段获取动态ID
J*aScript类型检查_j*ascript代码规范
MAC的“快捷指令”怎么同步到iPhone_MAC利用iCloud同步所有设备的自动化指令
PHP中高效并行检查多链接状态的教程
Vue.js 图片显示异常排查:理解应用挂载范围与DOM ID唯一性
火锅吃太多会怎样 火锅吃太多会上火吗
Golang如何实现Web文件静态资源服务器_Golang静态资源服务器开发与实践
QQ邮箱网页版入口登录 QQ邮箱在线邮箱官方通道
age动漫网站入口 age动漫官网直接访问入口
神庙逃亡小游戏在线玩 神庙逃亡小游戏入口
将JSON对象数组转置为键值对列表的实用指南
PHP中SSG-WSG API的AES加密实践:正确使用初始化向量
LINQ to XML为何解析失败? 深入理解C# XDocument的异常处理
如何在CSS中使用浮动制作导航栏_float实现水平菜单
天眼查企业查询官网入口 天眼查官方网页版查询
QQ邮箱登录官网首页 腾讯QQ邮箱网页入口
期待已久:小米17 Ultra、小米首款NAS本月登场
J*aScript实现单选按钮与关联输入框的联动禁用教程
Angular中单选按钮的正确使用与常见陷阱解析
mysql通配符支持数字匹配吗_mysql通配符能否用于数字匹配的解析
SteamMachine定价或为699美元 大家想入手吗?
AO3访问入口汇总 AO3网页版同人作品一键直达
Safari怎么安装扩展程序 浏览器插件安装与管理方法【详解】
cad如何更改注释性对象的比例_cad注释性比例调整方法
C++如何检测键盘输入_C++ _kbhit与_getch函数非阻塞输入
实现分段式页面滚动导航:CSS与J*aScript教程
ArrayList与LinkedList核心操作的Big-O复杂度分析
css卡片内容溢出如何处理_使用overflow隐藏或scroll显示内容
CSS实现侧边栏导航项全宽圆角悬停背景效果
Windows 11怎么彻底关闭定位_Windows 11服务中禁用Geolocation
一加 14R 快充无反应_一加 14R 充电优化
Bilibili动漫最新防封地址发布-Bilibili动漫2025年最稳正版入口推荐
狙击外星人小游戏开始_狙击外星人小游戏立即开始
Golang如何优化CPU绑定任务分配策略_Golang CPU任务分配优化实践
Golang如何优雅处理error_Golang error处理最佳实践总结
大象笔记网页版入口 印象笔记网页版登录入口
c++ 命名空间怎么用 c++ namespace使用指南
Python中如何避免重复条件判断:利用数据结构实现动态逻辑
Python自定义类排序:解决lambda键值访问TypeError的实践指南
谷歌google账号注册详细步骤 谷歌账号注册官方教程
PySpark中高效提取字符串右侧可变长度数字:使用regexp_extract
处理嵌套交互式控件:前端可访问性指南
J*aScript中localStorage数据的获取、清洗与格式化教程
QQ邮箱在线登录平台 QQ邮箱个人邮箱网页版入口
在Go Martini框架中高效服务动态生成图像的实践指南
电脑IP地址怎么查 查看本机IP地址的几种方法
火狐浏览器占用内存高卡顿怎么办 火狐浏览器性能优化设置技巧
Linux如何排查内存不足OOME问题_LinuxOOM分析教程


2025-12-01
浏览次数:次
返回列表
t;<p>t1 = threading.Thread(target=worker_1)
t2 = threading.Thread(target=worker_2)</p><p>t1.start()
t2.start()</p><p>t1.join()
t2.join()