Huang

淘宝 柏林

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::

  最近项目里面的一段千年代码出了问题,这个问题以前也出现过,不过不是那么明显,这次迁移机器由以前的4台机子变成2台以后问题被放大,最终不得不解决,特此分析一下。

 

先放出问题的代码

 

 private AlimamaCodeDAO alimamaCodeDAO;

    private Cache cache;

    /**
     * @param cache the cache to set
     */
    public void setCache(Cache cache) {
        this.cache = cache;
    }
    private Map codeMap; // KEYCODE与KEYNAME


    public List<AlimamaCodeDO> getAlimamaCodeByKey(String key) throws BOException {
        initCodeMap();
        return (List<AlimamaCodeDO>) codeMap.get(key);
    }

    private void initCodeMap() throws BOException {
        try {
            //Element element = cache.get(CacheKeyConstants.ALIMAMACODE_KEY);
            //if (element == null) {
                List codes = alimamaCodeDAO.findAllAlimamaCode();
                codeMap = new HashMap();
                for (int i = 0; i < codes.size(); i++) {
                    AlimamaCodeDO codeDo = (AlimamaCodeDO) codes.get(i);
                    if (!codeMap.containsKey(codeDo.getKey())) {
                        List list = new ArrayList();
                        list.add(codeDo);
                        codeMap.put(codeDo.getKey(), list);
                    } else {
                        ((List) codeMap.get(codeDo.getKey())).add(codeDo);
                    }
                }
                //element = new Element(CacheKeyConstants.ALIMAMACODE_KEY, (Serializable) codeMap);
                //cache.put(element);
            //}
            //codeMap = (Map) element.getValue();
        } catch (DAOException e) {
            throw new BOException("获取系统编码表时出现异常", e);
        }
    }

这一段代码有点漏洞百出,在调用getAlimamaCodeByKey的时候,高并发下,会出现hashmap的死锁,导致cpu100%。至于这个代码为什么写出这样,就暂时不叙述了,就来分析一下出现死锁的原因是什么。

 

每一次调用getAlimamaCodeByKey的时候,首先是去初始化这个hashmap,在初始化时,这个hashmap

void transfer(Entry[] newTable) {
        Entry[] src = table;
        int newCapacity = newTable.length;
        for (int j = 0; j < src.length; j++) {
            Entry<K,V> e = src[j];
            if (e != null) {
                src[j] = null;
                do {
                    Entry<K,V> next = e.next;
                    int i = indexFor(e.hash, newCapacity);
                    e.next = newTable[i];
                    newTable[i] = e;
                    e = next;
                } while (e != null);
            }
        }
    }


死锁就出现在了while (e != null);从上面的代码看来,每一个线程进来都先执行 codeMap = new HashMap();这个时候codeMap是空的,所以在执行下面的操作的时候进入了某一个不可以随意

更改状态的代码中,再加上高并发,一直被new HashMap(),while一直被执行,变成了死循环。cpu就瞬间飙升到100%,一直持续到请求数降低的时候。


最后解决办法:重构这部分代码,这部分代码本来就是写的不正确。再将HashMap改为ConcurrentHashMap,线程安全的Map。


线上观察很多天,一切正常。


posted on 2010-12-28 19:40  Baichuan  阅读(6229)  评论(0)    收藏  举报