簡體   English   中英

緩存注釋信息的地圖是否需要同步?

[英]Does a map that caches annotation info need to be synchronized?

我們正在使用HashMap來緩存對方法的注釋的查找。 使用Spring的AnnotationUtils.findAnnotation檢索注釋 不使用緩存會導致嚴重的性能下降。

我們的實現看起來像這樣:

public class SomeService {

    // Caches annotations on methods. The value can be null!
    private static final Map<Method, MyAnnotation> ANNOTATION_CACHE = new HashMap<Method, MyAnnotation>();

    private MyAnnotation findAnnotation(Method m) {
        if (ANNOTATION_CACHE.containsKey(m)) {
            return ANNOTATION_CACHE.get(m);
        }

        MyAnnotation a = AnnotationUtils.findAnnotation(m, MyAnnotation.class);
        ANNOTATION_CACHE.put(m, a);

        return a;
    }

    public void doSomethingWith(Class<?> clazz) {
        for (Method m : clazz.getMethods()) {
            MyAnnotation a = findAnnotation(m);
            if (a != null) {
                // do something with annotation a
            }
        }
    }
}

現在的問題是,是否需要同步對ANNOTATION_CACHE映射的訪問。 可能發生的最糟糕的情況是,兩個並行線程將相同的(m,a)對放入緩存映射中,這不會造成傷害,不是嗎?

我的第一個想法是使用ConcurrentHashMap,但它不允許使用null值(如果方法沒有注釋=> null,則在此需要)。 使用Collections.synchronizedMap()並使每個對地圖的訪問同步也是不理想的,因為經常調用此doSomethingWith()方法。

因此,在這種情況下,是否真的需要同步對HashMap的訪問? 緩存在運行時的永不更改,並且鍵/值對僅插入一次就不會刪除,但會被讀取很多次。

有什么想法嗎?

如果您有一個階段專門用於映射,而另一個階段則專門從中讀取映射,那么您就不需要並發集合。 您還可以通過使用不變的地圖寫入后階段包裝地圖來確保地圖保持不變。

例如,使用番石榴的不可變地圖

ImmutableMap.copyOf(map);


如果您預見到對集合的並發讀/寫/刪除訪問,那么您絕對應該使用ConcurrentHashMap; 由於讀/寫/刪除操作不是原子操作,因此您可能會得到一些非常奇怪的結果。


我的第一個想法是使用ConcurrentHashMap,但是它不允許使用null值(如果方法沒有注釋=> null,則在此需要此值)

然后,不要首先插入null值 更好的是,從地圖上刪除現有密鑰。

現在的問題是,是否需要同步對ANNOTATION_CACHE映射的訪問。 可能發生的最糟糕的情況是,兩個並行線程將相同的(m,a)對放入緩存映射中,這不會造成傷害,不是嗎?

是的,如果第一個看跌期權需要擴展支持哈希圖的數組,可能會造成傷害

如果在第一個put擴展哈希圖的同時調用第二個put,則可能會發生不良且不可預測的結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM