Python并发编程:多线程-死锁现象与递归锁

本文介绍了在Python中死锁的概念,通过实例展示了死锁如何在并发线程中发生,以及如何通过使用递归锁(RLock)来避免死锁,强调了递归锁在支持多次资源获取的重要性。
摘要由CSDN通过智能技术生成

一  死锁现象

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

from threading import Thread, Lock

import time

mutexA = Lock()

mutexB = Lock()

class MyThread(Thread):

    def run(self):

        self.func1()

        self.func2()

    def func1(self):

        mutexA.acquire()

        print('\033[41m%s 拿到A锁\033[0m' % self.name)

        mutexB.acquire()

        print('\033[42m%s 拿到B锁\033[0m' % self.name)

        mutexB.release()

        mutexA.release()

    def func2(self):

        mutexB.acquire()

        print('\033[43m%s 拿到B锁\033[0m' % self.name)

        time.sleep(3)

        mutexA.acquire()

        print('\033[44m%s 拿到A锁\033[0m' % self.name)

        mutexA.release()

        mutexB.release()

     

if __name__ == '__main__':

    for in range(10):

        = MyThread()

        t.start()

  执行效果

1

2

3

4

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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

# 递归锁

from threading import Thread, RLock

import time

mutexA = mutexB = RLock()       # 一个线程拿到锁,counter加1,该线程内又碰到加锁的情况,则counter继续加1,这期间所有其他线程都只能等待,等待该线程释放所有锁,即counter递减到0为止

class MyThread(Thread):

    def run(self):

        self.func1()

        self.func2()

         

    def func1(self):

        mutexA.acquire()

        print('\033[41m%s 拿到A锁\033[0m' % self.name)

        mutexB.acquire()

        print('%s 拿到B锁' % self.name)

        mutexB.release()

        mutexA.release()

    def func2(self):

        mutexB.acquire()

        print('\033[43m%s 拿到B锁\033[0m' % self.name)

        mutexA.acquire()

        print('%s 拿到A锁' % self.name)

        mutexA.release()

        mutexB.release()

if __name__ == '__main__':

    for in range(10):

        = MyThread()

        t.start()

  • 17
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值