关于J2EE中死锁问题的研究
http://tech.ddvip.com 2006年11月21日 社区交流
本文详细介绍关于J2EE中死锁问题的研究
如上所述,即使不存在并发,此代码也将导致死锁。当bulkLoadData调用executeUpdate方法时,它更新现有的数据库行,这涉及为该行获取写锁。对updateBatchStatus的嵌套EJB调用将在单独的数据库连接上执行,并尝试执行一个非常相似的查询,但它将阻塞,因为不能获取必需的写锁。从数据库的角度来说,只要提交或回滚第一个连接的事务,第二个连接就可以继续。但是,Java虚拟机不允许在完成所有对updateBatchStatus的调用前完成bulkLoadD调用,这样就出现了死锁情形。
该示例表明,一个更新会阻塞另一个更新,所以它会在任何数据库中导致死锁。如果初始更新查询是一个简单的选择查询,那么该示例仅在使用基于锁的并发控制的数据库上导致死锁,在这种数据库中,一个连接的读锁可以阻止另一个连接获取写锁。不管在哪种情况下,此类死锁即不依赖于同步,也不依赖于负载,而且线程转储将显示一个等待数据库响应的Java线程,但该线程与两个有效的数据库连接相关联。在这些数据库连接中,有一个将处于空闲状态,但会阻塞其他连接。
此情形有多种具体的变种,可以涉及多个线程和两个以上的数据库连接。例如,外部EJB调用的数据库连接可能已经获取了数据库锁,该锁阻塞了另一个无关数据库连接的继续,但这个无关数据库连接已经获取了阻塞嵌套EJB调用的数据库操作的锁。这个特例是依赖于同步的,并将显示多个等待数据库响应的Java线程。其中至少有一个Java线程将与两个活动数据库连接相关联。
跨资源死锁情形之3:Java虚拟机锁与数据库锁相冲突
第三种死锁情形发生在数据库锁与Java虚拟机锁并存的时候。在这种情况下,一个线程占有一个数据库锁并尝试获取Java虚拟机锁(尝试进入同步的锁)。同时,另一个线程占有Java虚拟机锁并尝试获取数据库锁。再次地,数据库发现一个连接阻塞了另一个连接,但由于无法阻止连接继续,所以不会检测到死锁。Java虚拟机发现同步的锁中有一个线程,并有另一个尝试进入的线程,所以即使Java虚拟机能检测到死锁并对它们进行处理,它还是不会检测到这种情况。
来源:bea 作者:Michael Nonemacher 责编:豆豆技术应用