关于J2EE中死锁问题的研究

http://tech.ddvip.com   2006年11月21日    社区交流

本文详细介绍关于J2EE中死锁问题的研究

  这种死锁情况总是在特定的代码路径中出现(每次执行这些特定的操作时),还是依赖于两个或两个以上同时执行的代码路径呢?

  涉及的数据库连接是什么?每个连接占有的数据库锁是什么?每个连接尝试获取的数据库锁是什么?每个数据库连接响应的Java虚拟机线程是什么?   下一小节介绍了三种常见的发生跨资源死锁的情形。

  跨资源死锁情形之1:客户端的增加导致资源池耗尽

  我们要介绍的第一种死锁情形是单纯由于负载而造成的,即资源池太小,而每个线程需要的资源超过了池中的可用资源。例如,考虑一个使用数据库连接的EJB调用,执行一个嵌套的EJB调用(使用同一连接池中不同的数据库连接)。例如,如果该嵌套的EJB调用声明为RequiresNew,就会出现死锁情形。

  在正常负载或者有足够大小的连接池的情况下,EJB调用将从池中获取一个数据库连接,然后调用嵌套的EJB。嵌套的EJB调用将从池中获取另一个数据库连接,提交内部事务,然后向池返回连接。外部EJB调用将提交自己的事务,并向池返回其连接。

  但是,假设连接池最多有10个连接,同时有10个对外部EJB的并发调用。这些线程中每一个都需要一个数据库连接用来清空池。现在,每个线程都执行嵌套的EJB调用(需要获取第二个数据库连接)。则所有线程都不能继续,但又都不放弃自己的第一个数据库连接。这样,10个线程都将被死锁。

  如果研究此类死锁情形,会发现线程转储中有大量等待获取资源的线程,以及同等数量的空闲且未阻塞的活动数据库连接。当应用程序死锁时,如果可以在运行时检测连接池,应该能确认连接池实际上已空。

  修复此类死锁的方法包括:增加连接池的大小或者重构代码,以便单个线程不需要同时使用很多数据库连接。如果单线程需要的最大数据库连接数为M,且可能的最大并发调用数为N,则要避免此问题,在池中所需的最小连接数为(N*(M01))+1。或者可以设置内部EJB调用以使用不同的连接池,即使外部调用的连接池为空,内部调用也能使用自己的连接池继续。

来源:bea    作者:Michael Nonemacher    责编:豆豆技术应用

正在加载评论...