python 防死锁机制
https://www.cnblogs.com/wongbingming/p/9035575.html
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
在编写多线程程序时,可能无意中就会写了一个死锁。可以说,死锁的形式有多种多样,但是本质都是相同的,都是对资源不合理竞争的结果。
以本人的经验总结,死锁通常以下几种
- 同一线程,嵌套获取同把锁,造成死锁。
- 多个线程,不按顺序同时获取多个锁。造成死锁
对于第一种,上面已经说过了,使用可重入锁。
主要是第二种。可能你还没明白,是如何死锁的。
举个例子。
线程1,嵌套获取A,B两个锁,线程2,嵌套获取B,A两个锁。
由于两个线程是交替执行的,是有机会遇到线程1获取到锁A,而未获取到锁B,在同一时刻,线程2获取到锁B,而未获取到锁A。由于锁B已经被线程2获取了,所以线程1就卡在了获取锁B处,由于是嵌套锁,线程1未获取并释放B,是不能释放锁A的,这是导致线程2也获取不到锁A,也卡住了。两个线程,各执一锁,各不让步。造成死锁。
经过数学证明,只要两个(或多个)线程获取嵌套锁时,按照固定顺序就能保证程序不会进入死锁状态。
那么问题就转化成如何保证这些锁是按顺序的?
有两个办法
- 人工自觉,人工识别。
- 写一个辅助函数来对锁进行排序。
第一种,就不说了。
第二种,可以参考如下代码
import threading from contextlib import contextmanager # Thread-local state to stored information on locks already acquired _local = threading.local() @contextmanager def acquire(*locks): # Sort locks by object identifier locks = sorted(locks, key=lambda x: id(x)) # Make sure lock order of previously acquired locks is not violated acquired = getattr(_local,'acquired',[]) if acquired and max(id(lock) for lock in acquired) >= id(locks[0]): raise RuntimeError('Lock Order Violation') # Acquire all of the locks acquired.extend(locks) _local.acquired = acquired try: for lock in locks: lock.acquire() yield finally: # Release locks in reverse order of acquisition for lock in reversed(locks): lock.release() del acquired[-len(locks):]
如何使用呢?
import threading x_lock = threading.Lock() y_lock = threading.Lock() def thread_1(): while True: with acquire(x_lock): with acquire(y_lock): print('Thread-1') def thread_2(): while True: with acquire(y_lock): with acquire(x_lock): print('Thread-2') t1 = threading.Thread(target=thread_1) t1.daemon = True t1.start() t2 = threading.Thread(target=thread_2) t2.daemon = True t2.start()
看到没有,表面上thread_1
的先获取锁x,再获取锁y
,而thread_2
是先获取锁y
,再获取x
。
但是实际上,acquire
函数,已经对x
,y
两个锁进行了排序。所以thread_1
,hread_2
都是以同一顺序来获取锁的,是不是造成死锁的。
python 防死锁机制的更多相关文章
- Python的GIL机制与多线程编程
GIL 全称global interpreter lock 全局解释锁 gil使得python同一个时刻只有一个线程在一个cpu上执行字节码,并且无法将多个线程映射到多个cpu上,即不能发挥多个cpu ...
- 防刷票机制研究和.NET HttpRequest Proxy
最近应朋友之约 测试他做的投票网站 防刷票机制能力如何,下面有一些心得和体会. 朋友网站用PHP写的,走的是HttpRequest,他一开始认为IP认证应该就差不多了.但说实话这种很low,手动更换代 ...
- Python GIL 多线程机制 (C source code)
最近阅读<Python源码剖析>对进程线程的封装解释: GIL,Global Interpreter Lock,对于python的多线程机制非常重要,其如何实现的?代码中实现如下: 指向一 ...
- 路由信息协议(RIP)的防环机制
防环机制 1-记数最大值(maximum hop count):定义最大跳数(最大为15跳),当跳数为16跳时,目标为不可达. 2-水平分割(split horizon):从一个接口学习到的路由不会再 ...
- python的反射机制
转载自:http://www.cnblogs.com/feixuelove1009/p/5576206.html 对编程语言比较熟悉的朋友,应该知道"反射"这个机制.Python作 ...
- python 的import机制2
http://blog.csdn.net/sirodeng/article/details/17095591 python 的import机制,以备忘: python中,每个py文件被称之为模块, ...
- 说说API的防重放机制
说说API的防重放机制 我们在设计接口的时候,最怕一个接口被用户截取用于重放攻击.重放攻击是什么呢?就是把你的请求原封不动地再发送一次,两次...n次,一般正常的请求都会通过验证进入到正常逻辑中,如果 ...
- Python垃圾回收机制 总结
Python 垃圾回收机制 内存管理 Python中的内存管理机制的层次结构提供了4层,其中最底层则是C运行的malloc和free接口,往上的三层才是由Python实现并且维护的,第一层则是在第0层 ...
- 简单谈谈python的反射机制
转:http://www.jb51.net/article/87479.htm 本文主要介绍python中的反射,以及该机制的简单应用,熟悉JAVA的程序员,一定经常和Class.forName打交道 ...
随机推荐
- 解决win10无线无故断网,重启才恢复正常的情况【原】
最初以为是路由器问题 ,但是别人电脑都好好的呀,而且我自己的手机也是好好的能正常上网,所以只能从自身电脑找问题了,目测就是无线网卡出问题了.经过一番百度,原来是win10自动开启了省模式,运行一段时间 ...
- Neural Networks and Deep Learning 课程笔记(第三周)浅层神经网络(Shallow neural networks)
3.1 神经网络概述(Neural Network Overview ) (神经网络中,我们要反复计算a和z,最终得到最后的loss function) 3.2 神经网络的表示(Neural Netw ...
- Nginx proxy开启cache缓存
proxy_temp_path /tmp/proxy_temp_dir; // 设置缓存位置 proxy_cache_path /tmp/proxy_cache_dir levels = : keys ...
- Linux - 系统基础操作
wall # 给其它用户发消息 whereis ls # 查找命令的目录 which # 查看当前要执行的命令所在的路径 clear # 清空整个屏幕 reset # 重新初始化屏幕 cal # 显示 ...
- 绘图QPainter-画刷
Qt提供的画刷风格: Qt.TexturePattern 自定义图像画刷 线性渐变 QLinearGradientPattern QLinearGradient需要传入的参数为需要进行渐变的区域坐 ...
- 单行纯文本框QLineEdit
继承 QWidget 天子骄龙
- NOIP2016 D2-T3 愤怒的小鸟
看了题解之后知道,是状压dp. 一.首先预处理一个$2^n$次方的fpow[]数组 fpow[]=; ;i<=;i++)fpow[i]=(fpow[i-]<<); 二.然后预处理一个 ...
- 2、Saltstack的数据系统
一.Grains grains是salt用来收集minion端底层系统信息的接口.比如,操作系统type.域名 .IP地址.内存及其他相关系统属性信息等.存储在minion端,用于保存minion ...
- 后端python基础
- jquery 学习(三) - 遍历操作
HTML代码 <p>1111</p> <p>1111</p> <p>1111</p> <p>1111</p&g ...