关于J2EE中死锁问题的研究

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

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

  当处理此情形的实例时,将有一个等待数据库响应的Java线程和一个等待获取Java虚拟机锁的线程。每个线程将与一个数据库连接相关联,其中一个连接阻塞另一个连接。修复方法是占有Java虚拟机锁时避免执行数据库操作,可以重写leCache的get()方法,如下所示:

  public Object get(String key) {
  synchronized(this) {
    if (cache.containsKey(key)) {
     return cache.get(key);
    }
  }
  Object value = queryForValue(key);
  synchronized(this) {
    cache.put(key, value);
  }
  return value;
} 

  既然现在我们知道了会发生此死锁情况,就可以使用Thread.holdsLock()向queryForValue方法添加检查以尝试避免死锁情况:

  private Object queryForValue(String key) {
   assert(!Thread.holdsLock(this));
   return executeQuery(...);
}

  上例中的Thread.holdsLock()很有用,但是只有在我们知道需要留心哪个锁时它才会发挥作用。如果有一个类似的方法可以确定当前线程占有哪个Java虚拟机锁,那么会很有用。任何执行任何种类的RPC调用、数据库访问等的代码片段都可以抛出异常或记录警告,指示在占有Java虚拟机锁时执行这些操作会有危险。

  注意:虽然我们修复了上例中的死锁问题,但它仍有缺陷,因为在提交updateData的事务之前清空了缓存。如果在调用clearCache后、提交updateData事务前出现缓存缺失,则该缓存将加载旧数据,因为新数据尚未可见。这里的修复方法是仅在提交更改后清空缓存。注意,这只在MVCC数据库中发生。在基于锁的数据库中,挂起的update将阻塞缓存的读操作,所以在提交update的事务后缓存才能读取正确值。

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

正在加载评论...