并发情况下synchronized死锁

2014-11-24 09:12:35 · 作者: · 浏览: 1
存在缺陷的代码:
public class DataPropertyIdAndNameRepositoryImpl{  
    /** 发布标志 */  
    private volatile boolean                      publishFlag;  
  
    public Integer getStandardId(int dataId, String propertyName) {  
        if (!publishFlag) {  
            loadToCache();  
        }  
        Integer standardId = 0;  
        Map propertyIdMap = propertyIdLocalCache.get(dataId);  
        if (propertyIdMap != null) {  
            standardId = propertyIdMap.get(propertyName);  
        }  
        return standardId;  
    }  
  
    public synchronized boolean loadToCache() {  
        try {  
            DataPropertyIdAndName dataPropertyIdAndName = dataPropertyIdAndNameService  
                .queryDataPropertyIdAndName();  
            publishFlag = true;  
        } catch (Exception e) {  
            publishFlag = false;  
        }  
        return publishFlag;  
    }  
}  

存在缺陷的流程:
a. 绿色表示第一个线程,蓝色表示第二个线程。
b. 黄色模块的代码为synchronized标记的代码,并发情况下只会有一个线程执行此方法。
c. 绿色线程执行到紫色模块时,蓝色线程等待进入黄色模块。
d. 蓝色线程执行抛异常,导致publishFlag被置为false。
e. 此时再次有线程进入,判断publishFlag仍为false,因此导致重复不断加载loadToCache.
public class DataPropertyIdAndNameRepositoryImpl{  
    /** 发布标志 */  
    private volatile boolean                      publishFlag;  
  
    public Integer getStandardId(int dataId, String propertyName) {  
        if (!publishFlag) {  
            loadToCache();  
        }  
        Integer standardId = 0;  
        Map propertyIdMap = propertyIdLocalCache.get(dataId);  
        if (propertyIdMap != null) {  
            standardId = propertyIdMap.get(propertyName);  
        }  
  
        return standardId;  
    }  
  
    public synchronized boolean loadToCache() {  
        try {  
  
            // 双检锁  
            if (publishFlag) {  
                return publishFlag;  
            }  
  
            DataPropertyIdAndName dataPropertyIdAndName = dataPropertyIdAndNameService.queryDataPropertyIdAndName();  
            publishFlag = true;  
  
        } catch (Exception e) {  
            publishFlag = false;  
        }  
  
        return publis