死锁

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

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

如下代码:

  1. from threading import Thread, Lock, RLock
  2. import time
  3.  
  4. # 这个函数,先让拿筷子,再拿面条,
  5. def eat1(args, Chopsticks_lock, Noodles_lock):
  6. Chopsticks_lock.acquire() # 拿钥匙
  7. print('%s拿到了筷子'%args)
  8. Noodles_lock.acquire() # 拿钥匙
  9. print('%s拿到了面条'%args)
  10. print('%s吃到了面条'%args)
  11. Noodles_lock.release() # 还钥匙
  12. Chopsticks_lock.release() # 还钥匙
  13.  
  14. # 这个函数,先让那面条,再让拿筷子。
  15. def eat2(args, Chopsticks_lock, Noodles_lock):
  16. Noodles_lock.acquire()
  17. print('%s拿到了面条' % args)
  18. time.sleep(0.1) # 让睡0.1面,这样更容易,一个线程拿到面条,一个线程拿到筷子,出现阻塞,出现死锁。
  19. Chopsticks_lock.acquire()
  20. print('%s拿到了筷子'%args)
  21. print('%s吃到了面条'%args)
  22. Noodles_lock.release()
  23. Chopsticks_lock.release()
  24.  
  25. # 创建两个锁,分别给面条和筷子加锁。
  26. Chopsticks_lock = Lock()
  27. Noodles_lock = Lock()
  28. Thread(target=eat1, args=('小明', Chopsticks_lock, Noodles_lock)).start()
  29. Thread(target=eat2, args=('小红', Chopsticks_lock, Noodles_lock)).start()
  30. Thread(target=eat1, args=('小兰', Chopsticks_lock, Noodles_lock)).start()
  31. Thread(target=eat2, args=('小军', Chopsticks_lock, Noodles_lock)).start()

打印结果:

  1. 小明拿到了筷子
  2. 小明拿到了面条
  3. 小明吃到了面条
  4. 小红拿到了面条
  5. 小兰拿到了筷子

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

如何解决?

引入递归锁。

递归锁RLock

  1. from threading import Thread, Lock, RLock
  2. import time
  3.  
  4. def eat1(args, Chopsticks_lock, Noodles_lock):
  5. Chopsticks_lock.acquire()
  6. print('%s拿到了筷子'%args)
  7. Noodles_lock.acquire()
  8. print('%s拿到了面条'%args)
  9. print('%s吃到了面条'%args)
  10. Noodles_lock.release()
  11. Chopsticks_lock.release()
  12.  
  13. def eat2(args, Chopsticks_lock, Noodles_lock):
  14. Noodles_lock.acquire()
  15. print('%s拿到了面条' % args)
  16. time.sleep(0.1)
  17. Chopsticks_lock.acquire()
  18. print('%s拿到了筷子'%args)
  19. print('%s吃到了面条'%args)
  20. Noodles_lock.release()
  21. Chopsticks_lock.release()
  22.  
  23. Chopsticks_lock = Noodles_lock = RLock()
  24.  
  25. Thread(target=eat1, args=('小明', Chopsticks_lock, Noodles_lock)).start()
  26. Thread(target=eat2, args=('小红', Chopsticks_lock, Noodles_lock)).start()
  27. Thread(target=eat1, args=('小兰', Chopsticks_lock, Noodles_lock)).start()
  28. Thread(target=eat2, args=('小军', Chopsticks_lock, Noodles_lock)).start()

打印结果:

  1. 小明拿到了筷子
  2. 小明拿到了面条
  3. 小明吃到了面条
  4. 小红拿到了面条
  5. 小红拿到了筷子
  6. 小红吃到了面条
  7. 小兰拿到了筷子
  8. 小兰拿到了面条
  9. 小兰吃到了面条
  10. 小军拿到了面条
  11. 小军拿到了筷子
  12. 小军吃到了面条

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

结束!

死锁的原因及解决办法RLock递归锁的更多相关文章

  1. SQL Server死锁产生原因及解决办法 .

    其实所有的死锁最深层的原因就是一个:资源竞争 表现一: 一个用户A 访问表A(锁住了表A),然后又访问表B,另一个用户B 访问表B(锁住了表B),然后企图访问表A,这时用户A由于用户B已经锁住表B,它 ...

  2. Oracle死锁产生的原因和解决办法

    如果有两个会话,每个会话都持有另一个会话想要的资源,此时就会发生死锁.用下面实验来说明死锁的产生原因和解决办法.SESSION1:SQL> create table t2 as select * ...

  3. mysql数据库死锁的产生原因及解决办法

    这篇文章主要介绍了mysql数据库锁的产生原因及解决办法,需要的朋友可以参考下   数据库和操作系统一样,是一个多用户使用的共享资源.当多个用户并发地存取数据 时,在数据库中就会产生多个事务同时存取同 ...

  4. HttpClient的CircularRedirectException异常原因及解决办法

    HttpClient的CircularRedirectException异常原因及解决办法 这两天在使用我自己爬虫抓取网页的时候总是出现 org.apache.http.client.ClientPr ...

  5. jquery ajax success 函数 异步调用方法中不能给全局变量赋值的原因及解决办法

    jquery ajax success 函数 异步调用方法中不能给全局变量赋值的原因及解决办法   在调用一个jquery的ajax方法时我们有时会需要该方法返回一个值或者给某个全局变量赋值,可是我们 ...

  6. 各种编码问题产生原因以及解决办法---------响应编码,请求编码,URL编码

     响应编码 产生原因以及解决办法: 示例: package cn.yzu; import java.io.IOException; import javax.servlet.ServletExcept ...

  7. .Net内存泄露原因及解决办法

    .Net内存泄露原因及解决办法 1.    什么是.Net内存泄露 (1).NET 应用程序中的内存 您大概已经知道,.NET 应用程序中要使用多种类型的内存,包括:堆栈.非托管堆和托管堆.这里我们需 ...

  8. php_curl.dll libssh2.dll 始终无法加载的原因 及解决办法

    在StackOverflow得到最终原因及解决办法 http://stackoverflow.com/questions/16424117/php-unable-to-load-php-curl-dl ...

  9. mysql保存中文乱码的原因和解决办法

    当你遇到这个mysql保存中文乱码问题的时候,期待找到mysql保存中文乱码的原因和解决办法这样一篇能解决问题的文章是多么激动人心.    也许30%的程序员会选择自己百度,结果发现网友已经贴了很多类 ...

随机推荐

  1. Wireshark抓包实例诊断TCP连接问题

    转载请在文首保留原文出处:EMC中文支持论坛https://community.emc.com/go/chinese  介绍 前文论述了TCP基础知识,从本节开始,通过TCP抓包实例来诊断TCP常见问 ...

  2. delphi 响应鼠标进入控件消息

    procedure MSGEnter(var msg:TMessage);message CM_MOUSEENTER;//响应进入的消息 procedure MSGLeave(var msg: TMe ...

  3. springboot配置双数据源 MySQL和SqlServer

    1. pom文件的驱动jar包加上去, compile 'com.microsoft.sqlserver:mssql-jdbc:6.2.2.jre8' 2. application.yml sprin ...

  4. Jmeter压力测试(简单的http请求)-实例

    服务端系分提供的某接口样例为: 评估后可采用使用jmeter进行压力测试的步骤为: 启动jmeter:在bin下点击jmeter.bat,运行jmeter 2. 创建测试计划: 默认启动jmeter时 ...

  5. 使用Nodpad++正则替换

    例如有以下格式数据: 现在需要将每一行的10位长度的数字串后面增加等号“=”

  6. 【PMP】易混淆知识点

    一.混淆概念 德尔菲技术 德尔菲技术是组织专家达成一致意见的一种方法.项目专家匿名参与其中.组织者使用调查问卷就重要的项目议题征询意见,然后对专家的答卷进行归纳,并把结果反馈给专家做进一步评论.这个过 ...

  7. 升级SilverLight为5.1.50907.0后,VS调试时报“无法启动调试--未安装 Silverlight Developer 运行时。请安装一个匹配版本”的处理办法

    作者: zyl910 一.问题 今天需要调试一个SilverLight程序.运行时ie弹出了一个升级提示,于是手贱点了升级. 随后便悲剧了,VS调试时报"无法启动调试--未安装 Silver ...

  8. manjaro折腾手记

    以前装过Arch,有点折腾,写了个hello world就卸载了.没用过AUR,甚至也没去了解. 听说manjaro继承Arch,几乎开箱即用,对硬件支持非常好,源里面的软件更新非常快.但是没有装中文 ...

  9. R语言之Random Forest随机森林

    什么是随机森林? 随机森林就是通过集成学习的思想将多棵树集成的一种算法,它的基本单元是决策树,而它的本质属于机器学习的一大分支——集成学习(Ensemble Learning)方法.随机森林的名称中有 ...

  10. linux驱动工程面试必问知识点

    linux内核原理面试必问(由易到难) 简单型 1:linux中内核空间及用户空间的区别?用户空间与内核通信方式有哪些? 2:linux中内存划分及如何使用?虚拟地址及物理地址的概念及彼此之间的转化, ...