- Python 基础
- Python - 首页
- Python - 概述
- Python - 历史
- Python - 特性
- Python vs C++
- Python - Hello World 程序
- Python - 应用领域
- Python - 解释器
- Python - 环境搭建
- Python - 虚拟环境
- Python - 基本语法
- Python - 变量
- Python - 数据类型
- Python - 类型转换
- Python - Unicode 系统
- Python - 字面量
- Python - 运算符
- Python - 算术运算符
- Python - 比较运算符
- Python - 赋值运算符
- Python - 逻辑运算符
- Python - 位运算符
- Python - 成员运算符
- Python - 身份运算符
- Python - 运算符优先级
- Python - 注释
- Python - 用户输入
- Python - 数字
- Python - 布尔值
- Python 控制语句
- Python - 控制流
- Python - 决策
- Python - if 语句
- Python - if else
- Python - 嵌套 if
- Python - Match-Case 语句
- Python - 循环
- Python - for 循环
- Python - for-else 循环
- Python - while 循环
- Python - break 语句
- Python - continue 语句
- Python - pass 语句
- Python - 嵌套循环
- Python 函数 & 模块
- Python - 函数
- Python - 默认参数
- Python - 关键字参数
- Python - 仅限关键字参数
- Python - 位置参数
- Python - 仅限位置参数
- Python - 可变参数
- Python - 变量作用域
- Python - 函数注解
- Python - 模块
- Python - 内置函数
- Python 字符串
- Python - 字符串
- Python - 字符串切片
- Python - 修改字符串
- Python - 字符串连接
- Python - 字符串格式化
- Python - 转义字符
- Python - 字符串方法
- Python - 字符串练习
- Python 列表
- Python - 列表
- Python - 访问列表元素
- Python - 修改列表元素
- Python - 添加列表元素
- Python - 删除列表元素
- Python - 遍历列表
- Python - 列表推导式
- Python - 排序列表
- Python - 复制列表
- Python - 合并列表
- Python - 列表方法
- Python - 列表练习
- Python 元组
- Python - 元组
- Python - 访问元组元素
- Python - 更新元组
- Python - 解包元组
- Python - 遍历元组
- Python - 合并元组
- Python - 元组方法
- Python - 元组练习
- Python 集合
- Python - 集合
- Python - 访问集合元素
- Python - 添加集合元素
- Python - 删除集合元素
- Python - 遍历集合
- Python - 合并集合
- Python - 复制集合
- Python - 集合运算符
- Python - 集合方法
- Python - 集合练习
- Python 字典
- Python - 字典
- Python - 访问字典元素
- Python - 修改字典元素
- Python - 添加字典元素
- Python - 删除字典元素
- Python - 字典视图对象
- Python - 遍历字典
- Python - 复制字典
- Python - 嵌套字典
- Python - 字典方法
- Python - 字典练习
- Python 数组
- Python - 数组
- Python - 访问数组元素
- Python - 添加数组元素
- Python - 删除数组元素
- Python - 遍历数组
- Python - 复制数组
- Python - 反转数组
- Python - 排序数组
- Python - 合并数组
- Python - 数组方法
- Python - 数组练习
- Python 文件处理
- Python - 文件处理
- Python - 写入文件
- Python - 读取文件
- Python - 重命名和删除文件
- Python - 目录
- Python - 文件方法
- Python - OS 文件/目录方法
- Python - OS 路径方法
- 面向对象编程
- Python - OOPs 概念
- Python - 类 & 对象
- Python - 类属性
- Python - 类方法
- Python - 静态方法
- Python - 构造函数
- Python - 访问修饰符
- Python - 继承
- Python - 多态
- Python - 方法重写
- Python - 方法重载
- Python - 动态绑定
- Python - 动态类型
- Python - 抽象
- Python - 封装
- Python - 接口
- Python - 包
- Python - 内部类
- Python - 匿名类和对象
- Python - 单例类
- Python - 包装器类
- Python - 枚举
- Python - 反射
- Python 错误 & 异常
- Python - 语法错误
- Python - 异常
- Python - try-except 块
- Python - try-finally 块
- Python - 抛出异常
- Python - 异常链
- Python - 嵌套 try 块
- Python - 用户自定义异常
- Python - 日志记录
- Python - 断言
- Python - 内置异常
- Python 多线程
- Python - 多线程
- Python - 线程生命周期
- Python - 创建线程
- Python - 启动线程
- Python - 线程连接
- Python - 线程命名
- Python - 线程调度
- Python - 线程池
- Python - 主线程
- Python - 线程优先级
- Python - 守护线程
- Python - 线程同步
- Python 同步
- Python - 线程间通信
- Python - 线程死锁
- Python - 中断线程
- Python 网络编程
- Python - 网络编程
- Python - Socket 编程
- Python - URL 处理
- Python - 泛型
- Python 库
- NumPy 教程
- Pandas 教程
- SciPy 教程
- Matplotlib 教程
- Django 教程
- OpenCV 教程
- Python 杂项
- Python - 日期 & 时间
- Python - 数学
- Python - 迭代器
- Python - 生成器
- Python - 闭包
- Python - 装饰器
- Python - 递归
- Python - 正则表达式
- Python - PIP
- Python - 数据库访问
- Python - 弱引用
- Python - 序列化
- Python - 模板
- Python - 输出格式化
- Python - 性能测量
- Python - 数据压缩
- Python - CGI 编程
- Python - XML 处理
- Python - GUI 编程
- Python - 命令行参数
- Python - 文档字符串
- Python - JSON
- Python - 发送邮件
- Python - 扩展
- Python - 工具/实用程序
- Python - GUIs
- Python 高级概念
- Python - 抽象基类
- Python - 自定义异常
- Python - 高阶函数
- Python - 对象内部
- Python - 内存管理
- Python - 元类
- Python - 使用元类进行元编程
- Python - 模拟和存根
- Python - 猴子补丁
- Python - 信号处理
- Python - 类型提示
- Python - 自动化教程
- Python - Humanize 包
- Python - 上下文管理器
- Python - 协程
- Python - 描述符
- Python - 诊断和修复内存泄漏
- Python - 不可变数据结构
- Python 有用资源
- Python - 问答
- Python - 在线测验
- Python - 快速指南
- Python - 参考
- Python - 速查表
- Python - 项目
- Python - 有用资源
- Python - 讨论
- Python 编译器
- NumPy 编译器
- Matplotlib 编译器
- SciPy 编译器
Python - 线程死锁
死锁可以描述为一种并发故障模式。它是在程序中出现的一种情况,其中一个或多个线程等待一个永远不会发生的条件。结果,线程无法继续执行,程序卡住或冻结,并且必须手动终止。
死锁情况可能在您的并发程序中以多种方式出现。死锁永远不会有意开发,相反,它们实际上是代码中的副作用或错误。
线程死锁的常见原因列在下面:
尝试两次获取同一互斥锁的线程。
相互等待的线程(例如 A 等待 B,B 等待 A)。
当线程未能释放资源(例如锁、信号量、条件、事件等)。
以不同顺序获取互斥锁的线程(例如,未能执行锁排序)。
如何在 Python 线程中避免死锁
当多线程应用程序中的多个线程尝试访问同一资源时,例如对同一文件执行读/写操作,可能会导致数据不一致。因此,使用锁定机制同步对资源的并发访问非常重要。
Python 的threading模块提供了一种易于实现的锁定机制来同步线程。您可以通过调用Lock()类创建一个新的锁对象,该类将锁初始化为未锁定状态。
使用 Lock 对象的锁定机制
Lock类的对象有两种可能的状态:锁定或未锁定,最初在创建时处于未锁定状态。锁不属于任何特定线程。
Lock 类定义了acquire() 和 release() 方法。
acquire() 方法
acquire()方法更改锁的状态从未锁定到锁定。除非可选的 blocking 参数设置为 True,否则它会立即返回,在这种情况下,它会等待直到获取锁。
以下是此方法的语法:
Lock.acquire(blocking, timeout)
其中,
blocking - 如果设置为 False,则表示不阻塞。如果带有 blocking 设置为 True 的调用将被阻塞,则立即返回 False;否则,将锁设置为锁定并返回 True。
timeout - 指定获取锁的超时时间。
此方法的返回值为 True,如果锁成功获取;否则为 False。
release() 方法
当状态被锁定时,另一个线程中的此方法将其更改为解锁状态。这可以从任何线程调用,而不仅仅是从获取锁的线程调用。
以下是release()方法的语法:
Lock.release()
release()方法只能在锁定状态下调用。如果尝试释放一个未锁定的锁,将会引发RuntimeError错误。
当锁被锁定时,将其重置为解锁状态,并返回。如果任何其他线程被阻塞等待锁解锁,则允许其中恰好一个线程继续执行。此方法没有返回值。
示例
在下面的程序中,两个线程尝试调用synchronized()方法。其中一个线程获取锁并获得访问权限,而另一个线程则等待。当第一个线程的run()方法完成时,锁被释放,第二个线程可以使用synchronized方法。
当两个线程都join后,程序结束。
from threading import Thread, Lock import time lock=Lock() threads=[] class myThread(Thread): def __init__(self,name): Thread.__init__(self) self.name=name def run(self): lock.acquire() synchronized(self.name) lock.release() def synchronized(threadName): print ("{} has acquired lock and is running synchronized method".format(threadName)) counter=5 while counter: print ('**', end='') time.sleep(2) counter=counter-1 print('\nlock released for', threadName) t1=myThread('Thread1') t2=myThread('Thread2') t1.start() threads.append(t1) t2.start() threads.append(t2) for t in threads: t.join() print ("end of main thread")
它将产生以下输出:
Thread1 has acquired lock and is running synchronized method ********** lock released for Thread1 Thread2 has acquired lock and is running synchronized method ********** lock released for Thread2 end of main thread
用于同步的信号量对象
除了锁之外,Python的threading模块还支持信号量,它提供了一种其他的同步技术。它是著名的计算机科学家Edsger W. Dijkstra发明的一种最古老的同步技术之一。
信号量的基本概念是使用一个内部计数器,每个acquire()调用都会递减它,每个release()调用都会递增它。计数器永远不会低于零;当acquire()发现它为零时,它会阻塞,等待直到其他线程调用release()。
threading模块中的Semaphore类定义了acquire()和release()方法。
acquire() 方法
如果在进入时内部计数器大于零,则将其减一并立即返回True。
如果在进入时内部计数器为零,则阻塞直到被对release()的调用唤醒。一旦被唤醒(并且计数器大于0),则将其减一并返回True。每个对release()的调用将唤醒恰好一个线程。线程唤醒的顺序是任意的。
如果blocking参数设置为False,则不阻塞。如果一个没有参数的调用会阻塞,则立即返回False;否则,执行与没有参数调用时相同的事情,并返回True。
release() 方法
释放一个信号量,将内部计数器加一。当它在进入时为零,并且其他线程正在等待它再次大于零时,唤醒n个这些线程。
示例
此示例演示了如何在Python中使用Semaphore对象来控制多个线程对共享资源的访问,以避免Python多线程程序中的死锁。
from threading import * import time # creating thread instance where count = 3 lock = Semaphore(4) # creating instance def synchronized(name): # calling acquire method lock.acquire() for n in range(3): print('Hello! ', end = '') time.sleep(1) print( name) # calling release method lock.release() # creating multiple thread thread_1 = Thread(target = synchronized , args = ('Thread 1',)) thread_2 = Thread(target = synchronized , args = ('Thread 2',)) thread_3 = Thread(target = synchronized , args = ('Thread 3',)) # calling the threads thread_1.start() thread_2.start() thread_3.start()
它将产生以下输出:
Hello! Hello! Hello! Thread 1 Hello! Thread 2 Thread 3 Hello! Hello! Thread 1 Hello! Thread 3 Thread 2 Hello! Hello! Thread 1 Thread 3 Thread 2