死锁和递归锁

死锁和递归锁

码农世界 2024-05-27 后端 95 次浏览 0个评论

【一】死锁

【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锁

转载请注明来自码农世界,本文标题:《死锁和递归锁》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,95人围观)参与讨论

还没有评论,来说两句吧...

Top