一次同步不当的bug记录。

昨天晚上,收到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次方个构造函数。晕啊,我真不想看你这么多的文档:(
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值