高效實現Map的原子更新操作(Hystrix的InternMap源碼解析)

最近在學習Hystrix框架時,看到有一段代碼,挺有意思的,代碼如下:

代碼清單1-1

public class InternMap<K, V> {
    private final ConcurrentMap<K, V> storage = new ConcurrentHashMap<K, V>();
    private final ValueConstructor<K, V> valueConstructor;

    public interface ValueConstructor<K, V> {
        V create(K key);
    }

    public V interned(K key) {
        V existingKey = storage.get(key);
        V newKey = null;
        if (existingKey == null) {
            newKey = valueConstructor.create(key);
            existingKey = storage.putIfAbsent(key, newKey);
        }
        return existingKey != null ? existingKey : newKey;
    }
}

省略了部分非關注代碼……

ValueConstructor是函數式接口,作用是傳入key獲得value值,JDK8引入的新特性。


重點關注上面的interned方法:先是判斷key對應的value是否已存在:如果不存在,則通過ValueConstructor產生新的value,並存入storage中。最後返回已存在的value

邏輯很簡單,但是上面的代碼卻寫得很複雜,感覺有點囉嗦,一般寫法如下:

代碼清單1-2

    public V interned(K key) {
        V existingValue = storage.get(key);
        if (existingValue == null) {
            existingValue = valueConstructor.create(key);
            storage.put(key, existingValue);
        }
        return existingValue;
    }

仔細分析下上面簡單寫法,存在着線程安全問題。由於未進行同步處理,可能出現兩個線程同時進入if語句塊,從而導致每個線程獲得了不同的existingValue,這顯然是不希望看到的。


再回過頭來看代碼1-1,就明白作者的深意了。通過ConcurrentHashMap提供的線程安全的putIfAbsent方法,保證了storage存入時的線程安全,同時通過對newKey、existingKey(實際上應該取名爲newValue、existingVaule)兩個線程內變量值判斷進行返回,保證了整個方法操作的原子性。

這種實現線程安全的方式,沒有用同步代碼塊等比較低效的同步方式,確實是一種高效實現Map的原子更新方式,不得不爲作者的深思熟慮感到佩服.......


最後,我想問句:元芳,你怎麼看?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章