对J2EE中死锁问题的研究 - 编程入门网
续,但这个无关数据库连接已经获取了阻塞嵌套EJB调用的数据库操作的锁。这个特例是依赖于同步的,并将显示多个等待数据库响应的Java线程。其中至少有一个Java线程将与两个活动数据库连接相关联。
跨资源死锁情形之3:Java虚拟机锁与数据库锁相冲突 第三种死锁情形发生在数据库锁与Java虚拟机锁并存的时候。在这种情况下,一个线程占有一个数据库锁并尝试获取Java虚拟机锁(尝试进入同步的锁)。同时,另一个线程占有Java虚拟机锁并尝试获取数据库锁。再次地,数据库发现一个连接阻塞了另一个连接,但由于无法阻止连接继续,所以不会检测到死锁。Java虚拟机发现同步的锁中有一个线程,并有另一个尝试进入的线程,所以即使Java虚拟机能检测到死锁并对它们进行处理,它还是不会检测到这种情况。 为了说明此种死锁情形,我们以一个简单的(不完善的)read-through cache为例。该cache是数据库表中备份的HashMap。如果出现缓存命中,它就从HashMap返回一个值。但在缓存缺失的情况下,它将从数据库读取值,将其添加到HashMap,然后返回该值,如清单2所示。 清单 2 这是一个简单的遍历cache。注意:get()方法是同步的,这是因为我们访问了非线程安全容器,并要求containsKey/put组合在缓存缺失时是原子性的。 该cache相当简单易懂:它约定,如果更改支持缓存的表中的数据,则应调用clearCache(),这样缓存就可以避免处理陈旧的数据。产生的缓存缺失将相应地重新进入缓存。 我们现在来考虑可以更改此数据并清除缓存的代码:
对J2EE中死锁问题的研究(4)时间:2011-01-05 bea Michael Nonemacher上面的代码在简单的例子中能正常运行。但是,在使用基于锁的并发控制的数据库中,updateData中的查询将阻止queryForValue中的选择查询的执行,因为update语句将获取一个写锁,从而阻止选择查询获取同一数据行上的读锁。如果同步没有问题,一个线程可以尝试读取缓存中的给定值,并在另一个线程在数据库中更新该值时得到缓存缺失。如果数据库先执行update语句,它将阻塞select语句继续执行。但是,执行select语句的线程来自同步的get方法,所以它获取了SimpleCache上的锁。要返回updateData中的线程,它必须调用clearCache(),但不能获取锁(clearCache()是同步的)。 当处理此情形的实例时,将有一个等待数据库响应的Java线程和一个等待获取Java虚拟机锁的线程。每个线程将与一个数据库连接相关联,其中一个连接阻塞另一个连接。修复方法是占有Java虚拟机锁时避免执行数据库操作,可以重写leCache的get()方法,如下所示:
|
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |