一 死锁现象

所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程,如下就是死锁

from threading import Thread
from threading import Lock
import time # 实例化两把不同的锁
mutexA = Lock()
mutexB = Lock() class MyThread(Thread): def run(self):
self.f1()
self.f2() def f1(self):
mutexA.acquire()
print("%s拿到A锁" % self.name) # Thread类自带name属性 mutexB.acquire()
print("%s拿到B锁" % self.name)
mutexB.release() mutexA.release() def f2(self):
mutexB.acquire()
print("%s拿到B锁" % self.name) # Thread类自带name属性
time.sleep(0.1)
mutexA.acquire() print("%s拿到A锁" % self.name)
mutexA.release() mutexB.release() if __name__ == "__main__":
for i in range(1,11):
t = MyThread()
t.start()

执行结果

Thread-1拿到A锁
Thread-1拿到B锁
Thread-1拿到B锁
Thread-2拿到A锁 # 出现死锁,整个程序卡住

解决方法:

二 递归锁

递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。

这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。

上面的例子如果使用RLock代替Lock,则不会发生死锁,

二者的区别是:

递归锁可以连续acquire多次,每acquire一次计数器加1,

只要计数不为0,就不能被其他线程抢到。只有计数为0时,才能被其他线程抢到acquire。释放一次计数器-1

而互斥锁只能加锁acquire一次,想要再加锁acquire,就需要release解之前的锁

from threading import Thread
from threading import RLock
import time # 实例化一把锁,mutexA 和mutexB公用一把锁
mutexB = mutexA = RLock() class MyThread(Thread): def run(self):
self.f1()
self.f2() def f1(self):
mutexA.acquire()
print("%s拿到A锁" % self.name) # Thread类自带name属性 mutexB.acquire()
print("%s拿到B锁" % self.name)
mutexB.release() mutexA.release() def f2(self):
mutexB.acquire()
print("%s拿到B锁" % self.name) # Thread类自带name属性
time.sleep(0.1)
mutexA.acquire() print("%s拿到A锁" % self.name)
mutexA.release() mutexB.release() if __name__ == "__main__":
for i in range(1,5):
t = MyThread()
t.start()
'''
Thread-1拿到A锁
Thread-1拿到B锁
Thread-1拿到B锁
Thread-1拿到A锁
Thread-2拿到A锁
Thread-2拿到B锁
Thread-2拿到B锁
Thread-2拿到A锁
Thread-4拿到A锁
Thread-4拿到B锁
Thread-4拿到B锁
Thread-4拿到A锁
Thread-3拿到A锁
Thread-3拿到B锁
Thread-3拿到B锁
Thread-3拿到A锁
Thread-5拿到A锁
Thread-5拿到B锁
Thread-5拿到B锁
Thread-5拿到A锁
'''

python 并发编程 多线程 死锁现象与递归锁的更多相关文章

  1. Python并发编程05 /死锁现象、递归锁、信号量、GIL锁、计算密集型/IO密集型效率验证、进程池/线程池

    Python并发编程05 /死锁现象.递归锁.信号量.GIL锁.计算密集型/IO密集型效率验证.进程池/线程池 目录 Python并发编程05 /死锁现象.递归锁.信号量.GIL锁.计算密集型/IO密 ...

  2. 并发编程-线程-死锁现象-GIL全局锁-线程池

    一堆锁 死锁现象 (重点) 死锁指的是某个资源被占用后,一直得不到释放,导致其他需要这个资源的线程进入阻塞状态. 产生死锁的情况 对同一把互斥锁加了多次 一个共享资源,要访问必须同时具备多把锁,但是这 ...

  3. python 并发编程 多线程 目录

    线程理论 python 并发编程 多线程 开启线程的两种方式 python 并发编程 多线程与多进程的区别 python 并发编程 多线程 Thread对象的其他属性或方法 python 并发编程 多 ...

  4. python 之 并发编程(守护线程与守护进程的区别、线程互斥锁、死锁现象与递归锁、信号量、GIL全局解释器锁)

    9.94 守护线程与守护进程的区别 1.对主进程来说,运行完毕指的是主进程代码运行完毕2.对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕​详细解释:1.主 ...

  5. 并发编程~~~多线程~~~守护线程, 互斥锁, 死锁现象与递归锁, 信号量 (Semaphore), GIL全局解释器锁

    一 守护线程 from threading import Thread import time def foo(): print(123) time.sleep(1) print('end123') ...

  6. 并发编程(五)--GIL、死锁现象与递归锁、信号量、Event事件、线程queue

    一.GIL全局解释器锁 1.什么是全局解释器锁 GIL本质就是一把互斥锁,相当于执行权限,每个进程内都会存在一把GIL,同一进程内的多个线程,必须抢到GIL之后才能使用Cpython解释器来执行自己的 ...

  7. 并发编程(五)——GIL全局解释器锁、死锁现象与递归锁、信号量、Event事件、线程queue

    GIL.死锁现象与递归锁.信号量.Event事件.线程queue 一.GIL全局解释器锁 1.什么是全局解释器锁 GIL本质就是一把互斥锁,相当于执行权限,每个进程内都会存在一把GIL,同一进程内的多 ...

  8. python并发编程&多线程(二)

    前导理论知识见:python并发编程&多线程(一) 一 threading模块介绍 multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性 官网链 ...

  9. python并发编程&多线程(一)

    本篇理论居多,实际操作见:  python并发编程&多线程(二) 一 什么是线程 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程,一 ...

随机推荐

  1. WTL自定义控件:需要的头文件

    这两天自定义了一个Edit控件,继承自CEdit,如下: class CCheckEditEx : public CWindowImpl< CCheckEditEx, CEdit > 需要 ...

  2. JAVA笔记4-static关键字

    1.static方法中不能使用this关键字 2.例题:static成员变量用于计数     

  3. wx小程序知识点(六)

    六.生命周期 (1)onLoad    —— 加载时触发,只调用一次,可用来发送请求绑定数据.获取url中参数 (2)onShow   —— 页面显示时触发,每次显示都会执行,用来获取需要频繁更新的数 ...

  4. C# 父子窗体 传值

    子窗体 public event Action<List<DataGridViewRow>> myEvent; myEvent(List); 子窗体调用 父窗体 创建对象 fr ...

  5. hdu_1712(dp,背包)

    hdu_1712 \[dp[i][j]\] 表示前i个物品用了j天得到的最大收益 \[ dp[i][j] = max(dp[i-1][j],dp[i][j-k]+ k*v[i][k]) \qquad ...

  6. set集合 ,深浅拷贝

    一 之前内容的补充 1.join() 将列表转换成字符串 2.split()将字符串转换成列表 3列表和字典在进行For循环时是不可以删除的(准确的说是删除的不彻底)  删除操作需要先创建一个新的空列 ...

  7. /static/fonts/SIMYOU.TTF’ 字体

    /** * pdf 加水印 * * @return */ public byte[] pdfAddWaterMark(byte[] byes) { String fileName = UUID.ran ...

  8. 关于synchronized和ReentrantLock之多线程同步详解

    一.线程同步问题的产生及解决方案 问题的产生: Java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查),将会导致数据不准确,相互之间产生冲突. 如下例:假设有一个卖票 ...

  9. 删除oracle居家必备

  10. Charles 功能介绍说明和使用教程

    https://juejin.im/post/5b8350b96fb9a019d9246c4c http://blog.devtang.com/2015/11/14/charles-introduct ...