- Python 基础知识
- Python - 主页
- Python - 概述
- Python - 历史
- Python - 特性
- Python 与 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 - 决策
- Python - 如果有的话
- Python - 大小写匹配语句
- Python - for 循环
- Python - for-else 循环
- Python - While 循环
- Python-break语句
- Python-继续语句
- 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 - OOP 概念
- 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-套接字编程
- Python-URL 处理
- Python - 泛型
- Python 杂项
- Python - 日期和时间
- Python - 数学
- Python - 迭代器
- Python - 生成器
- Python - 闭包
- Python - 装饰器
- Python - 递归
- Python - 正则表达式
- Python-PIP
- Python-数据库访问
- Python - 弱引用
- Python-序列化
- Python - 模板
- Python - 输出格式
- Python-性能测量
- Python-数据压缩
- Python - CGI 编程
- Python - XML 处理
- Python - 图形用户界面编程
- Python - 命令行参数
- Python - 文档字符串
- Python-JSON
- Python-发送电子邮件
- Python - 进一步扩展
- Python - 工具/实用程序
- Python - 图形用户界面
- Python 问题与解答
- Python - 编程示例
- Python - 快速指南
- Python - 有用的资源
- Python - 讨论
Python-线程死锁
死锁可以被描述为并发失败模式。这是程序中的一种情况,其中一个或多个线程等待一个从未发生的条件。结果,线程无法继续进行,程序被卡住或冻结,必须手动终止。
在并发程序中,死锁情况可能以多种方式出现。死锁从来都不是故意造成的,相反,它们实际上是代码中的副作用或错误。
下面列出了线程死锁的常见原因 -
尝试两次获取相同互斥锁的线程。
相互等待的线程(例如,A 等待B,B 等待A)。
当线程无法释放锁、信号量、条件、事件等资源时
以不同顺序获取互斥锁的线程(例如,无法执行锁排序)。
如果多线程应用程序中多个线程尝试访问同一资源,例如对同一文件执行读/写操作,则可能会导致数据不一致。因此,并发处理的同步非常重要,这样当一个线程使用资源时,其他线程就可以锁定它。
Python 提供的线程模块包含一个易于实现的锁定机制,允许您同步线程。通过调用 Lock() 方法创建一个新锁,该方法返回新锁。
锁定对象
Lock 类的对象有两种可能的状态 - 锁定或解锁,首次创建时最初处于解锁状态。锁不属于任何特定线程。
Lock 类定义了 acquire() 和 release() 方法。
acquire() 方法
当状态为解锁时,该方法将状态更改为锁定并立即返回。该方法采用可选的阻塞参数。
句法
Lock.acquire(blocking, timeout)
参数
阻塞- 如果设置为 False,则意味着不阻塞。如果将阻塞设置为 True 的调用会阻塞,则立即返回 False;否则,将锁设置为锁定并返回 True。
如果获取锁成功,该方法的返回值为True;如果没有则为假。
release() 方法
当状态为锁定时,另一个线程中的此方法将其更改为解锁状态。这可以从任何线程调用,而不仅仅是已获取锁的线程
句法
Lock.release()
release() 方法只能在锁定状态下调用。如果尝试释放未锁定的锁,则会引发运行时错误。
当锁被锁定时,将其重置为解锁,然后返回。如果任何其他线程在等待锁解锁时被阻塞,则只允许其中一个线程继续进行。该方法没有返回值。
例子
在下面的程序中,两个线程尝试调用synchronized()方法。其中一个获得锁并获得访问权限,而另一个则等待。当第一个线程的 run() 方法完成时,锁被释放,并且同步方法可用于第二个线程。
当两个线程加入时,程序就结束了。
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 通过另一种称为信号量的机制来支持线程同步。它是由著名计算机科学家 Edsger W. Dijkstra 发明的最古老的同步技术之一。
信号量的基本概念是使用一个内部计数器,该计数器在每次 acquire() 调用时递减,并在每次 release() 调用时递增。计数器永远不会低于零;当 acquire() 发现它为零时,它会阻塞,等待其他线程调用release()。
threading 模块中的 Semaphore 类定义了 acquire() 和 release() 方法。
acquire() 方法
如果内部计数器在输入时大于零,则将其减一并立即返回 True。
如果内部计数器在进入时为零,则阻塞直到通过调用release()唤醒。一旦被唤醒(并且计数器大于 0),计数器减 1 并返回 True。每次调用release()都会唤醒一个线程。线程唤醒的顺序是任意的。
如果阻塞参数设置为False,则不阻塞。如果不带参数的调用会阻塞,则立即返回 False;否则,执行与不带参数调用时相同的操作,并返回 True。
release() 方法
释放一个信号量,将内部计数器加 1。当它在进入时为零并且其他线程正在等待它再次变得大于零时,唤醒其中的 n 个线程。
例子
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