- 浏览: 55158 次
- 性别:
- 来自: 北京
文章分类
最新评论
一. 如何检测死锁的根源
Java并不提供对死锁的检测机制。笔者认为常用分析Java代码问题的最有效的工具仍然是java thread
dump。当死锁发生时,JVM通常处于挂起状态,thread
dump可以给出静态稳定的信息,查找死锁只需要查找有问题的线程。Java虚拟机死锁发生时,从操作系统上观察,虚拟机的CPU占用率为零,很快会从
top或prstat的输出中消失。这时可以收集thread dump,查找"waiting for monitor
entry"的thread,如果大量thread都在等待给同一个地址上锁(因为对于Java,一个对象只有一把锁),这说明很可能死锁发生了。
为了确定问题,笔者建议在隔几分钟后再次收集一次thread
dump,如果得到的输出相同,仍然是大量thread都在等待给同一个地址上锁,那么肯定是死锁了。如何找到当前持有锁的线程是解决问题的关键。一般方
法是搜索thread
dump,查找"locked,找到持有锁的线程。如果持有锁的线程还在等待给另一个对象上锁,那么还是按上面的办法顺藤摸瓜,直到找到死锁的根源为止。
另外,在thread dump里还会经常看到这样的线程,它们是等待一个条件而主动放弃锁的线程。有时也需要分析这类线程,尤其是线程等待的条件。
二 几种常见死锁及对策
解决死锁没有简单的方法,这是因为线程产生死锁都各有各的原因,而且往往具有很高的负载。大多数软件测试产生不了足够多的负载,所以不可能暴露所有的线程错误。在这里中,笔者将讨论开发过程常见的4类典型的死锁和解决对策。
(1)数据库死锁
在数据库中,如果一个连接占用了另一个连接所需的数据库锁,则它可以阻塞另一个连接。如果两个或两个以
上的连接相互阻塞,则它们都不能继续执行,这种情况称为数据库死锁。
数据库死锁问题不易处理,通常数据行进行更新时,需要锁定该数据行,执行更新,然后在提交或回滚封闭事务时释放锁。由于数据库平台、配置的隔离级以及
查询提示的不同,获取的锁可能是细粒度或粗粒度的,它会阻塞(或不阻塞)其他对同一数据行、表或数据库的查询。基于数据库模式,读写操作会要求遍历或更新
多个索引、验证约束、执行触发器等。每个要求都会引入更多锁。此外,其他应用程序还可能正在访问同一数据库模式中的某些对象,并获取不同应用程序所具有的
锁。
所有这些因素综合在一起,数据库死锁几乎不可能被消除了。值得庆幸的是,数据库死锁通常是可恢复的:当数据库发现死锁时,它会强制销毁一个连接(通常
是使用最少的连接),并回滚其事务。这将释放所有与已经结束的事务相关联的锁,至少允许其他连接中有一个可以获取它们正在被阻塞的锁。
由于数据库具有这种典型的死锁处理行为,所以当出现数据库死锁问题时,数据库常常只能重试整个事务。当数据库连接被销毁时,会抛出可被应用程序捕获的异
常,并标识为数据库死锁。如果允许死锁异常传播到初始化该事务的代码层之外,则该代码层可以启动一个新事务并重做先前所有工作。
当出现问题就重试,由于数据库可以自由地获取锁,所以几乎不可能保证两个或两个以上的线程不发生数据库死锁。此方法至少能保证在出现某些数据库死锁情况时,应用程序能正常运行。
(2)资源池耗尽死锁
客户端的增加导致资源池耗尽死锁是由于负载而造成的,即资源池太小,而每个线程需要的资源超过了池中的可用资源。假设连接池最多有10个连接,同时有
10个对外部并发调用。这些线程中每一个都需要一个数据库连接用来清空池。现在,每个线程都执行嵌套的调用。则所有线程都不能继续,但又都不放弃自己的第
一个数据库连接。这样,10个线程都将被死锁。
研究此类死锁,会发现线程存储中有大量等待获取资源的线程,以及同等数量的空闲且未阻塞的活动数据库连接。当应用程序死锁时,如果可以在运行时检测连接池,就能确认连接池实际上已空。
修复此类死锁的方法包括:增加连接池的大小或者重构代码,以便单个线程不需要同时使用很多数据库连接。或者可以设置内部调用使用不同的连接池,即使外部调用的连接池为空,内部调用也能使用自己的连接池继续。
(3)单线程、多冲突数据库连接死锁
对同一线程执行嵌套的调用有时出现死锁,此情形即使在非高负载系统中通常也会发生。当第一个(外部)连接已获取第二个(内部)连接所需要的数据库锁,
则第二个连接将永久阻塞第一个连接,并等待第一个连接被提交或回滚,这就出现了死锁情形。因为数据库没有注意到两个连接之间的关系,所以数据库不会将此情
形检测为死锁。这样即使不存在并发,此代码也将导致死锁。此情形有多种具体的变种,可以涉及多个线程和两个以上的数据库连接。
(4)Java虚拟机锁与数据库锁冲突
这种情形发生在数据库锁与Java虚拟机锁并存的时候。在这种情况下,一个线程占有一个数据库锁并尝试获取Java虚拟机锁。同时,另一个线程占有
Java虚拟机锁并尝试获取数据库锁。此时,数据库发现一个连接阻塞了另一个连接,但由于无法阻止连接继续,所以不会检测到死锁。Java虚拟机发现同步
的锁中有一个线程,并有另一个尝试进入的线程,所以即使Java虚拟机能检测到死锁并对它们进行处理,它还是不会检测到这种情况。
总而言之,JAVA应用程序中的死锁是一个大问题——它能导致整个应用程序慢慢终止,还很难被分离和修复,尤其是当开发人员不熟悉如何分析死锁环境的时候。
发表评论
-
给开发维护大型项目开发者的建议
2013-02-05 17:43 644假 设你是正在开发和维护一个包含2000个类并使用了很多框 ... -
高性能表现的网站
2012-11-02 17:43 637它展示了来自http://yahoo.com 的ht ... -
liunx 服务器 - im20
2012-10-25 10:32 723crontab -l 1 * * * * /usr/sbin ... -
I liunx 命令
2012-10-24 10:00 748grep 字符串查找 grep [OPTI ... -
liunx mysql5.5 master/slave 配置
2012-10-24 10:00 844grant all on *.* to 'root'@'% ... -
Linux一个mysql配置多端口
2012-10-24 10:01 5279Mysqld_multi 在一台服务器上运行多个 ... -
liunx mysql5.5 源码安装
2012-10-24 10:01 788首先到http://www.cmake.org/cmake/r ... -
聚簇索引与非聚簇索引
2012-10-23 17:33 0在《数据库原理》里面,对聚簇索引的解释是:聚簇索引的顺序就是数 ... -
Netlog的数据库及架构
2012-10-23 17:31 0Database Sharding@Netlog 详 ... -
复杂查询sql intersect ,union ,except
2012-10-24 10:01 838select * from (select userid ... -
JVM调优总结 -Xms -Xmx -Xmn -Xss
2012-10-25 10:33 632堆大小设置 JVM 中最大堆大小有三方面限制:相关操 ... -
多线程编程模型
2012-10-25 10:34 808一.加密技术分类 1.消息摘要算法(保证消息完整性) 摘要 ... -
mysql 优化
2012-10-25 10:33 976MySQL与优化技术 MySQL历史 1979 ... -
sql删除重复记录
2012-10-23 17:21 0delete from table where id in( ... -
在LINUX下的软件安装
2012-10-23 17:13 608在LINUX下的软件安装方式不外乎有三种。 1。。。RPM ... -
Too many open files
2012-10-23 17:07 672查看系统允许打开的最大文件数 #cat /proc/sy ... -
apache服务器查看网络爬虫记录的方法说明
2012-10-22 11:34 709问 :使用Apache服务器,如何查看哪些网站的蜘蛛来爬过自己 ...
相关推荐
java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁...
java 一个死锁的例子 java 一个死锁的例子 java 一个死锁的例子
Java中死锁的例子,非常的例子。经过本人验证
线程池里的线程等待等待队列里的线程执行,等待队列里的等待线程池里的完成,相互等待
Java解决死锁问题eclipse代码版
java线程实践,了解线程死锁,同步问题
之后,我们在Java分析工具Soot中实现了这一理论,并用它来分析Akka实现的基于行为者的Java程序,Akka是一个允许基于行为者进行编程的Java库。 我们认为,我们的分析可以检测出特定类型的通信僵局并获得精确的结果,...
Java死锁的问题分析与研究
java多线程死锁预防机制研究,java多线程死锁预防机制研究
Java多线程程序死锁检查 JCarder
2015 Oracle 技术嘉年华(OTN)分会场11何登成 - 管中窥豹——MySQL(InnoDB)死锁分析之道
1.1 一个不可思议的死锁 1 1.1.1 初步分析 3 1.2 如何阅读死锁日志 3 2.1 Delete操作的加锁逻辑 4 2.2 死锁预防策略 5 2.3
mysql死锁分析
本源代码是博客《Java 多线程编程之七:死锁(附源代码)》附带的实例性源代码。原博客链接地址:http://blog.csdn.net/defonds/archive/2010/01/26/5258120.aspx。
该文档详细分析了innodb的加锁原理、死锁原因以及处理方式
主要介绍了java线程死锁代码示例,分享了一个简单线程死锁的例子,需要的朋友可以参考下。
主要介绍了Java线程死锁实例及解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
死锁在java 线程如何解决?这个实例描述了几个人资源共享的情况
主要介绍了 Java 线程死锁的问题解决办法的相关资料,希望通过本大家能帮助到大家,遇到类似问题能够解决,需要的朋友可以参考下
这个对于定位死锁很重要,很简单。在运行java控制台的时候,都会用 java -classpath XXX org.XXX. main 这种方法 在管理控制台中按下ctrl + break 就能从界面上获得及时的堆栈信息了,但是这些信息很不方便。那么又...