死锁和递归锁

【一】死锁

【1】介绍

  • 死锁是指两个或多个进程,在执行过程中,因争夺资源而造成了互相等待的现象

  • 即两个或多个进程持有各自的锁并视图获取对方持有的锁,从而导致阻塞,不能继续执行,一直僵在这

  • 这种情况下,系统资源利用率极低,系统处于死循环状态

【2】例子

  • 要吃饭,必须具备盘子和筷子

  • 但是一个人拿着盘子等筷子。

  • 另一个人拿着筷子等盘子

【3】解决方法

  • 锁不要有多个,一个就足够

  • 如果真的发生了死锁的问题,必须迫使一方先交出锁

【4】示例

复制代码
from threading import Thread, Lock
import time
​
metexA = Lock()
metexB = Lock()
​
​
# 类只要加括号多次 产生的肯定不同的对象
# 如果你想要实现多次加括号等到的是相同的对象 - 单例模式
​
class MyThread(Thread):
    def run(self):
        self.func1()
        self.func2()
​
    def func1(self):
        metexA.acquire()
        # self.name :获取当前线程名
        print(f"{self.name} 抢到了A锁")
        metexB.acquire()
        print(f"{self.name} 抢到了B锁")
        metexB.release()
        metexA.release()
​
    def func2(self):
        metexB.acquire()
        # self.name: 获取当前线程名
        print(f"{self.name} 抢到了A锁")
        time.sleep(2)
        metexA.acquire()
        print(f"{self.name} 抢到了B锁")
        metexA.release()
        metexB.release()
​
​
def main():
    for i in range(10):
        t = MyThread()
        t.start()
​
​
if __name__ == '__main__':
    main()
    
# Thread-1 抢到了A锁
# Thread-1 抢到了B锁
# Thread-1 抢到了A锁
# Thread-2 抢到了A锁
# 线程卡死
# 开启十个线程,第一个线程走完第一圈 回到原地抢A 结果第二个线程已经抢到A了 导致AB卡死

【二】递归锁

【1】介绍

  • 递归锁(也叫可重入锁)是一种特殊的锁,它允许一个线程多次请求同一个锁,称为"递归地"请求锁

  • 在该线程释放锁之前,会对锁计数器进行累加操作,线程每成功获得一次锁时,都要进行相应的解锁操作,直到锁计数器清零才能完全释放该锁。

  • 递归锁能够保证同一线程在持有锁时能够再次获取该锁,而不被自己所持有的锁所阻塞,从而避免死锁的发生。

  • 但是注意要正常使用递归锁,避免过多地获取锁导致性能下降。

【2】示例

  • 可以被连续的 acquire 和 release

  • 但是只能被第一个抢到这把锁上执行上述操作

  • 他的内部有一个计数器,每acquire一次计数 +1 每release一次 计数-1

  • 只要计数不为0,那么其他人都无法抢到该锁

复制代码
from threading import Thread, RLock
import time
​
# 两个变量同时指向一把锁
metexA = metexB = RLock()
​
​
# 类只要加括号多次 产生的肯定不同的对象
# 如果你想要实现多次加括号等到的是相同的对象 - 单例模式
​
class MyThread(Thread):
    def run(self):
        self.func1()
        self.func2()
​
    def func1(self):
        metexA.acquire()
        # self.name :获取当前线程名
        print(f"{self.name} 抢到了A锁")
        metexB.acquire()
        print(f"{self.name} 抢到了B锁")
        metexB.release()
        metexA.release()
​
    def func2(self):
        metexB.acquire()
        # self.name: 获取当前线程名
        print(f"{self.name} 抢到了A锁")
        time.sleep(2)
        metexA.acquire()
        print(f"{self.name} 抢到了B锁")
        metexA.release()
        metexB.release()
​
​
def main():
    for i in range(10):
        t = MyThread()
        t.start()
​
​
if __name__ == '__main__':
    main()
    
# Thread-1 抢到了A锁
# Thread-1 抢到了B锁
# Thread-1 抢到了A锁
# Thread-1 抢到了B锁
# Thread-2 抢到了A锁
# Thread-2 抢到了B锁
# Thread-2 抢到了A锁
# Thread-2 抢到了B锁
相关推荐
光而不耀@lgy20 分钟前
C++初登门槛
linux·开发语言·网络·c++·后端
合新通信 | 让光不负所托1 小时前
【合新通信】浸没式液冷光模块与冷媒兼容性测试技术报告
大数据·网络·光纤通信
浩浩测试一下2 小时前
计算机网络中的DHCP是什么呀? 详情解答
android·网络·计算机网络·安全·web安全·网络安全·安全架构
ZVAyIVqt0UFji4 小时前
360 OpenStack支持IP SAN存储实现
网络·网络协议·tcp/ip·openstack
三思而后行,慎承诺5 小时前
tcp 和http 网络知识
网络·tcp/ip·http
JavaEdge.5 小时前
LangChain4j HTTP 客户端定制:解锁 LLM API 交互的更多可能性
网络·网络协议·http
Hy行者勇哥5 小时前
形象解释 HTTP 的四种常见请求方式及其中的区别联系
网络·网络协议·http
Cuit小唐6 小时前
TCP 协议:原理、机制与应用
网络·网络协议·tcp/ip
电鱼智能的电小鱼6 小时前
EFISH-SBC-RK3588无人机地面基准站项目
linux·网络·嵌入式硬件·机器人·无人机·边缘计算
电鱼智能的电小鱼6 小时前
基于 EFISH-SBC-RK3588 的无人机环境感知与数据采集方案
linux·网络·嵌入式硬件·数码相机·无人机·边缘计算