死锁的原因及解决办法RLock递归锁

死锁

说到死锁,可以讲一个科学家吃面的问题:

有几个科学家在一张桌子旁,桌子上只有一把筷子和一碗面,我们将面和筷子都加锁。这是可能会导致一个科学家抢到面,另一个科学家抢到筷子,这是就全部阻塞了,这就是死锁了。

如下代码:

from threading import Thread, Lock, RLock
import time

# 这个函数,先让拿筷子,再拿面条,
def eat1(args, Chopsticks_lock, Noodles_lock):
    Chopsticks_lock.acquire()  # 拿钥匙
    print('%s拿到了筷子'%args)
    Noodles_lock.acquire()  # 拿钥匙
    print('%s拿到了面条'%args)
    print('%s吃到了面条'%args)
    Noodles_lock.release()  # 还钥匙
    Chopsticks_lock.release()  # 还钥匙

# 这个函数,先让那面条,再让拿筷子。
def eat2(args, Chopsticks_lock, Noodles_lock):
    Noodles_lock.acquire()
    print('%s拿到了面条' % args)
    time.sleep(0.1)  # 让睡0.1面,这样更容易,一个线程拿到面条,一个线程拿到筷子,出现阻塞,出现死锁。
    Chopsticks_lock.acquire()
    print('%s拿到了筷子'%args)
    print('%s吃到了面条'%args)
    Noodles_lock.release()
    Chopsticks_lock.release()
    
# 创建两个锁,分别给面条和筷子加锁。
Chopsticks_lock = Lock()
Noodles_lock = Lock()
Thread(target=eat1, args=('小明', Chopsticks_lock, Noodles_lock)).start()
Thread(target=eat2, args=('小红', Chopsticks_lock, Noodles_lock)).start()
Thread(target=eat1, args=('小兰', Chopsticks_lock, Noodles_lock)).start()
Thread(target=eat2, args=('小军', Chopsticks_lock, Noodles_lock)).start()

打印结果:

小明拿到了筷子
小明拿到了面条
小明吃到了面条
小红拿到了面条
小兰拿到了筷子

看到小红拿到了面条,而小兰拿到了筷子,他们都需要对方拿到的资源来完成吃面条的整个过程,但是线程未使用完资源之前,不可被剥夺,并且线程拿不到需要的资源就会阻塞,就造成了死锁的情况。

如何解决?

引入递归锁。

递归锁RLock

from threading import Thread, Lock, RLock
import time


def eat1(args, Chopsticks_lock, Noodles_lock):
    Chopsticks_lock.acquire()
    print('%s拿到了筷子'%args)
    Noodles_lock.acquire()
    print('%s拿到了面条'%args)
    print('%s吃到了面条'%args)
    Noodles_lock.release()
    Chopsticks_lock.release()


def eat2(args, Chopsticks_lock, Noodles_lock):
    Noodles_lock.acquire()
    print('%s拿到了面条' % args)
    time.sleep(0.1)
    Chopsticks_lock.acquire()
    print('%s拿到了筷子'%args)
    print('%s吃到了面条'%args)
    Noodles_lock.release()
    Chopsticks_lock.release()


Chopsticks_lock = Noodles_lock = RLock()

Thread(target=eat1, args=('小明', Chopsticks_lock, Noodles_lock)).start()
Thread(target=eat2, args=('小红', Chopsticks_lock, Noodles_lock)).start()
Thread(target=eat1, args=('小兰', Chopsticks_lock, Noodles_lock)).start()
Thread(target=eat2, args=('小军', Chopsticks_lock, Noodles_lock)).start()

打印结果:

小明拿到了筷子
小明拿到了面条
小明吃到了面条
小红拿到了面条
小红拿到了筷子
小红吃到了面条
小兰拿到了筷子
小兰拿到了面条
小兰吃到了面条
小军拿到了面条
小军拿到了筷子
小军吃到了面条

值得注意的是,线程锁Lock是互斥锁,只有一把钥匙。而递归锁RLock是一个钥匙串的很多把钥匙,每个钥匙都可以开一把锁,但是只要一个进程拿到这串钥匙的其中一个钥匙,其他线程就拿不到钥匙了,这就是递归锁,就造成不了面条和筷子分别被两个线程拿到的情况了。

结束!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值