Dev Zone
偏执狂才能生存,人生/事业的路上需要再坚持一下
但是又怎么说得清坚持的结果,道得尽坚持的含义
Ofbiz2.1有两个bug,都涉及到线程安全性,小并发的时候不容易发现,大并发下有时候会出现,并发数越高出现的频度就比较高,尤其对于实体引擎的那个bug,在系统初始化的时候如果遭遇大并发,会有一定频度的出现。
 
1。entity engine的ModelEntity.getField方法存在线程安全隐患,会造成 XXXX is not a field of XXX的异常,以下是原有代码片断:

    
public ModelField getField(String fieldName) {
        
if (fieldName == nullreturn null;
        if (fieldsMap == null) {
            fieldsMap = new HashMap(fields.size());
            for (int i = 0; i < fields.size(); i++) {
                ModelField field = (ModelField) fields.get(i);
                fieldsMap.put(field.name, field);
        }
        return (ModelField) fieldsMap.get(fieldName);
    }

由于getField方法没有同步(会造成性能下降),因此红色标标注的那段代码存在线程安全问题,必须进行同步。在大并发下如果多个调用这个方法,最先调用的线程没有执行完循环的情况下,后续的线程通过最后的语句return的时候得到的就是Null(fieldsMap已经被第一个线程赋值了,后续线程不会进入红色标准的代码区域)。
修改后的代码如下:
   public ModelField getField(String fieldName) {
        
if (fieldName == nullreturn null;
        
if (fieldsMap == null) {
             createFields();
        }
        
return (ModelField) fieldsMap.get(fieldName);
    }

    
public synchronized void createFields()
    {
             fieldsMap 
= new HashMap(fields.size());
 
             
for (int i = 0; i < fields.size(); i++) {
                 ModelField field 
= (ModelField) fields.get(i);
 
                 fieldsMap.put(field.name, field);
             }
    }
 
这个Bug在3.0中已经被修正。
 
2。UtilCache.get方法同样存在线程安全隐患,会造成LinkedList.remove或者LinedList.addFirst的空值针异常,不注意还会以为是LinkedList的bug。以下是原代码片断:
    public Object get(Object key) {
        
if (key == null) {
            missCount
++;
            
return null;
        }
        UtilCache.CacheLine line 
= (UtilCache.CacheLine) cacheLineTable.get(key);
        
if (hasExpired(line)) {
            
// note that print.info in debug.properties cannot be checked through UtilProperties here, it would cause infinite recursion
            
// if (Debug.infoOn()) Debug.logInfo("Element has expired with key " + key);
            remove(key);
            line 
= null;
        }
        
if (line == null) {
            
// if (Debug.infoOn()) Debug.logInfo("Element not found with key " + key);
            missCount++;
            
return null;
        }
        
// if (Debug.infoOn()) Debug.logInfo("Element found with key " + key);
        hitCount++;
        if (maxSize > 0) {
            keyLRUList.remove(key);
            keyLRUList.addFirst(key);
        }

        return line.getValue();
    }
红色标准的部分是有问题的代码,修改后的代码如下:
    public Object get(Object key) {
        
if (key == null) {
            missCount
++;
            
return null;
        }
        UtilCache.CacheLine line 
= (UtilCache.CacheLine) cacheLineTable.get(key);
        
if (hasExpired(line)) {
            
// note that print.info in debug.properties cannot be checked through UtilProperties here, it would cause infinite recursion
            
// if (Debug.infoOn()) Debug.logInfo("Element has expired with key " + key);
            remove(key);
            line 
= null;
        }
        
if (line == null) {
            
// if (Debug.infoOn()) Debug.logInfo("Element not found with key " + key);
            missCount++;
            
return null;
        }
        
// if (Debug.infoOn()) Debug.logInfo("Element found with key " + key);
        hitCount++;
        
if (maxSize > 0) {
            synchronized ( 
this)
            {
                 keyLRUList.remove(key);
                 keyLRUList.addFirst(key);
            }
        }
        
return line.getValue();
    }

这个BUG在3.0种也修正了。
posted on 2005-05-17 22:07 dev 阅读(307) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: