- 浏览: 57271 次
- 性别:
- 来自: 北京
文章分类
最新评论
一. 如何检测死锁的根源
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 706假 设你是正在开发和维护一个包含2000个类并使用了很多框 ... -
高性能表现的网站
2012-11-02 17:43 668它展示了来自http://yahoo.com 的ht ... -
liunx 服务器 - im20
2012-10-25 10:32 761crontab -l 1 * * * * /usr/sbin ... -
I liunx 命令
2012-10-24 10:00 784grep 字符串查找 grep [OPTI ... -
liunx mysql5.5 master/slave 配置
2012-10-24 10:00 868grant all on *.* to 'root'@'% ... -
Linux一个mysql配置多端口
2012-10-24 10:01 5356Mysqld_multi 在一台服务器上运行多个 ... -
liunx mysql5.5 源码安装
2012-10-24 10:01 818首先到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 898select * from (select userid ... -
JVM调优总结 -Xms -Xmx -Xmn -Xss
2012-10-25 10:33 667堆大小设置 JVM 中最大堆大小有三方面限制:相关操 ... -
多线程编程模型
2012-10-25 10:34 840一.加密技术分类 1.消息摘要算法(保证消息完整性) 摘要 ... -
mysql 优化
2012-10-25 10:33 1012MySQL与优化技术 MySQL历史 1979 ... -
sql删除重复记录
2012-10-23 17:21 0delete from table where id in( ... -
在LINUX下的软件安装
2012-10-23 17:13 640在LINUX下的软件安装方式不外乎有三种。 1。。。RPM ... -
Too many open files
2012-10-23 17:07 718查看系统允许打开的最大文件数 #cat /proc/sy ... -
apache服务器查看网络爬虫记录的方法说明
2012-10-22 11:34 746问 :使用Apache服务器,如何查看哪些网站的蜘蛛来爬过自己 ...
相关推荐
3. **线程分析**:Visual VM提供线程的详细视图,显示线程状态、阻塞原因以及死锁检测,帮助调试多线程问题。 4. **方法和类的性能分析**:可以追踪方法调用和类加载,了解哪些代码段执行时间较长,优化性能关键...
Java虚拟机(JVM)是Java编程语言的核心组成部分,它为Java程序提供了运行环境,使得Java代码能够在不同的操作系统上“一次编写,到处运行”。在Java虚拟机1.4的时代,这是Java技术发展的一个重要里程碑,引入了许多...
总之,MyEclipse的VM插件是Java开发者不可或缺的工具,它强化了MyEclipse对JVM的支持,使开发者能够更好地管理和优化Java应用,提高开发效率和软件质量。结合Velocity这样的模板引擎,可以进一步提升Web应用开发的...
2. **使用JavaVM**:JavaVM是对整个JVM的引用,可以用来获取JNIEnv,同时也可以用来控制JVM的行为,如附加或分离线程。在JNI初始化时,JavaVM指针会作为参数传入,我们可以保存它以便后续使用。 回调Java方法还需要...
`com.tool.javavm`可能是一个Java项目的源代码包,其中包含了JVM的一些基础工具或者组件。这个包通常包含用于解析、加载、执行字节码的类和方法,可能还包括垃圾收集、内存管理、线程调度等JVM的关键功能。 `...
Visual VM是一款强大的Java性能分析工具,它为开发者提供了一种可视化的方式来监控和分析JVM(Java虚拟机)上的应用程序。1.3.6是Visual VM的一个版本,它包含了许多改进和增强,使得开发者能够更有效地理解和优化...
在Java中,有一些内置的工具可以用来监控和分析性能,包括内存使用、垃圾回收等方面。 首先,`jps`命令类似于Linux的`ps`命令,用于列出本地正在运行的Java进程ID。`jstat`工具则可以提供虚拟机(VM)的各种统计...
VisualVM是一个功能强大的Java虚拟机(JVM)监控、分析和故障排查工具,它提供了广泛的监控和分析功能,可帮助开发人员诊断和解决Java应用程序的性能问题。 主要功能: 1.CPU监控:显示Java进程的CPU使用率、线程...
5. **VM摘要**:显示Java虚拟机的详细信息,包括JVM版本、命令行参数等。 6. **MBeans**:显示管理Bean(MBeans)的信息,这是JMX的核心组件之一,用于监控和管理资源。 #### 六、案例分析 1. **内存分析**:通过...
JProfiler是一款强大的Java性能分析工具,它提供了全面的内存监控、线程分析以及CPU性能剖析等功能,帮助开发者深入理解应用程序的运行状态,找出潜在的性能瓶颈。 ### JProfiler的功能特性 1. **内存分析**:...
在“JAVA高级工程师2”这一主题中,我们将深入探讨Java编程语言在安全、多线程、图形用户界面(GUI)开发、游戏制作、网络设计以及虚拟机(VM)参数优化等多个核心领域的高级知识。虽然IO(输入/输出)部分涉及较少...
`jstack`用于打印Java进程的线程堆栈信息,有助于定位死锁或线程阻塞的问题。 10. **jinfo**:配置信息工具 `jinfo`可以查看或修改Java进程的系统属性和命令行选项。 11. **jcmd**:Java诊断命令 自Java 8开始...
在Java开发中,理解和优化JVM的性能至关重要,因此需要一些工具来帮助分析JVM的行为: - **jstack**:用于生成当前时刻线程快照,用于定位线程死锁、运行状态等问题。 - **jmap**:用于生成堆内存的快照,可以分析...
在这个"2008JAVA工程师高级培训教程8"中,重点显然集中在Java的安全性、线程管理、图形界面编程、游戏开发以及网络设计和虚拟机(VM)参数调整。尽管IO(输入/输出)部分涉及较少,但这些核心主题对于一个Java开发者...
6. **jstack**: jstack 用于生成Java线程的堆栈跟踪,帮助诊断线程阻塞或死锁等问题。通过`jstack process_id`,你可以看到每个线程当前的状态和调用堆栈。 7. **jstat**: jstat 提供了GC和类装载的统计信息,用于...
###### 1.5.2 gdb Subcommands for Java VM Debugging (用于Java VM调试的gdb子命令) - **功能**:提供了一系列专门针对Java虚拟机调试的命令。 - **应用场景**:在深入分析Java程序内部机制时必不可少。 ##### 1.6...
这些不同版本的VM可能在内存管理、垃圾收集、编译优化等方面存在差异,因此了解它们的特性对优化至关重要。 书中会遵循一定的编写约定,例如使用特定的术语和符号来帮助读者理解复杂的概念。作者可能还会提供代码...
- **死锁检测**:检查是否存在线程死锁的情况。 - **线程堆栈跟踪**:查看特定线程的堆栈跟踪信息。 ##### 4.4 查看CPU消耗情况 - **CPU使用率**:监控Java应用的整体CPU使用率。 - **线程CPU使用**:分析各个线程...
### 阿里内部资料——Java开发杂项:多线程并发详解 ...以上内容不仅涵盖了Java开发中多线程并发的具体实践,还涉及了远程调试、性能监控、线程分析等高级主题,为Java开发者提供了全面的技术指南。