论坛首页 Java企业应用论坛

一次同步不当的bug记录。

浏览 1729 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-02-25   最后修改:2009-02-25
OO
昨天晚上,收到QA报告,说页面里面一大堆数据无法显示。
别急,别急,先保护现场,用另外一台服务器在调试模式下继续测试,想办法复现这个问题。

到了晚上,问题终于又出现了。打开远程调试,检查一下运行线程,发现有一大堆用于抓取外部数据的Servlet线程不动了。
原来,一条记录指向了一个公司内部ip地址,员工下班关机之后,无法获取该记录,导致装载延迟。
而我们的开发人员在这里为了避免同一资源的多次解析,用了一个全局的同步锁,一下子其他数据也无法装载。

问题代码:
    Object data = getFromCache...;
    if (data != null) {
      return data;
    }
    synchronized (LOCK) {
        Object data =getFromCache...;
        if (data != null) {
           return data;
        }
        data = buildData..
        saveToCache...
        return data
    }


上面的代码看似还行,可是,确保了我们不会重复解析同一数据,但是,加锁加的不合适,一旦任何一个资源延迟,都将导致全部线程暂停。

给一下修改后的形式:
	private Map lockMap = new HashMap();
.....
	protected String getCachedResource(String url) throws Exception {
		String key =  url;
		Object data = getFromCache(key);
		if (data == null) {
			//获取资源对应的锁
			Object lock = requireLock(url);
			synchronized (lock) {
				data = parser.parse(url);
				saveToCache(key, data);
			}
			//删除锁
			lockMap.remove(key);
		}
		return (String) data;
	}

	private Object requireLock(Object key) {
		synchronized (lockMap) {
			Object lock = lockMap.get(key);
			if (lock == null) {
				lock = new Object();
				lockMap.put(key, lock);
			}
			return lock;
		}
	}

仍外抱怨一下繁琐的代码风格
一个内部类,构造函数最多带n个参数,能后呢,某些人为了可能的使用方便,居然给配上了2的n次方个构造函数。晕啊,我真不想看你这么多的文档:(
   发表时间:2009-02-25  
感觉没有解决问题:2个线程如果同时请求相同的url,一个被堵住了,另外一个还是在那边等待锁吧?
0 请登录后投票
   发表时间:2009-02-25   最后修改:2009-02-25
恩,这个是的,但是如果这个url有问题,抓不下来,我们再开100个线程估计也是没用的了。
我只是解决了一个url有问题导致其他url死锁的bug。

QW有其他办法吗?
0 请登录后投票
   发表时间:2009-02-25  
jindw 写道
恩,这个是的,但是如果这个url有问题,抓不下来,我们再开100个线程估计也是没用的了。
我只是解决了一个url有问题导致其他url死锁的bug。

QW有其他办法吗?

没有想到好办法,不过parser.parse(url)这个方法里面没有处理超时吗?如果有超时设定的话,就不会一直堵了。
0 请登录后投票
   发表时间:2009-02-25  
代码写的够烂的, 难道不会使用同步队列, 自己加个LOCK, 麻烦死了。
0 请登录后投票
   发表时间:2009-02-26   最后修改:2009-02-26
异常呢??
getFromCache不会抛出异常吗?

synchronized里面抛出异常会释放锁的
0 请登录后投票
   发表时间:2009-02-26   最后修改:2009-02-26
为什么会导致装载延迟,如果url不存在的话,是不是用url直接返回null,或者马上抛出异常。是不是用到了URLConnection包,那为什么不把超时时间设置短一点
0 请登录后投票
   发表时间:2009-02-26   最后修改:2009-02-26
case0079 写道
异常呢??
getFromCache不会抛出异常吗?

synchronized里面抛出异常会释放锁的


呵呵,我还真吧这个给忘了,低级错误^_^
谢谢谢谢。
0 请登录后投票
   发表时间:2009-02-26  
sdh5724 写道
代码写的够烂的, 难道不会使用同步队列, 自己加个LOCK, 麻烦死了。


能否详细一点呢?
我比较笨,呵呵
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics