简体   繁体   English

缓存注释信息的地图是否需要同步?

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

We are using a HashMap to cache the lookup of annotations on methods. 我们正在使用HashMap来缓存对方法的注释的查找。 The annotations are retrieved with Spring's AnnotationUtils.findAnnotation . 使用Spring的AnnotationUtils.findAnnotation检索注释 Not using the cache results in a drastic performance hit. 不使用缓存会导致严重的性能下降。

Our implementation looks somehow like: 我们的实现看起来像这样:

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
            }
        }
    }
}

The question now is if I need to synchronize the access to the ANNOTATION_CACHE Map or not. 现在的问题是,是否需要同步对ANNOTATION_CACHE映射的访问。 The worst thing that could happen is that two threads in parallel put the same (m, a) pair into the cache map, which would not hurt, isn't it? 可能发生的最糟糕的情况是,两个并行线程将相同的(m,a)对放入缓存映射中,这不会造成伤害,不是吗?

My first thought was to use the ConcurrentHashMap, but it does not allow null values (which is needed here if a method has no annotation => null). 我的第一个想法是使用ConcurrentHashMap,但它不允许使用null值(如果方法没有注释=> null,则在此需要)。 Using Collections.synchronizedMap() and synchronizing every access to the map also is not ideal, because this doSomethingWith() method is called very frequently. 使用Collections.synchronizedMap()并使每个对地图的访问同步也是不理想的,因为经常调用此doSomethingWith()方法。

So is it really necessary to synchronize the access to the HashMap in this case? 因此,在这种情况下,是否真的需要同步对HashMap的访问? The cache nevery changes at runtime and key/value pairs get inserted only once get never removed but will be read many times. 缓存在运行时的永不更改,并且键/值对仅插入一次就不会删除,但会被读取很多次。

Any thoughts? 有什么想法吗?

If you have a single phase where the map is exclusively written to and then a different phase where the map is exclusively read from, then you don't need a concurrent collection. 如果您有一个阶段专门用于映射,而另一个阶段则专门从中读取映射,那么您就不需要并发集合。 You could also make sure that the map remains unmodified by wrapping it with an immutable map post-write phase. 您还可以通过使用不变的地图写入后阶段包装地图来确保地图保持不变。

For example, using Guava's Immutable map : 例如,使用番石榴的不可变地图

ImmutableMap.copyOf(map);


If you foresee concurrent read/write/remove access to the collection, then you definitely should use ConcurrentHashMap; 如果您预见到对集合的并发读/写/删除访问,那么您绝对应该使用ConcurrentHashMap; because read/write/remove operations are not atomic, you could end up with some pretty strange results. 由于读/写/删除操作不是原子操作,因此您可能会得到一些非常奇怪的结果。


My first thought was to use the ConcurrentHashMap, but it does not allow null values (which is needed here if a method has no annotation => null) 我的第一个想法是使用ConcurrentHashMap,但是它不允许使用null值(如果方法没有注释=> null,则在此需要此值)

Then don't insert the null value in the first place; 然后,不要首先插入null值 better yet, remove the existing key from the map. 更好的是,从地图上删除现有密钥。

The question now is if I need to synchronize the access to the ANNOTATION_CACHE Map or not. 现在的问题是,是否需要同步对ANNOTATION_CACHE映射的访问。 The worst thing that could happen is that two threads in parallel put the same (m, a) pair into the cache map, which would not hurt, isn't it? 可能发生的最糟糕的情况是,两个并行线程将相同的(m,a)对放入缓存映射中,这不会造成伤害,不是吗?

Yes that can hurt if the first put need to expand the array backing the hashmap 是的,如果第一个看跌期权需要扩展支持哈希图的数组,可能会造成伤害

If the second put is called while the first put expands the hashmap, bad and unpredictable results can happend. 如果在第一个put扩展哈希图的同时调用第二个put,则可能会发生不良且不可预测的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM