简体   繁体   English

使用HashMap进行双重映射

[英]Double mapping with HashMap

We've been working on a piece of code for getting singeltons. 我们一直在开发一段获取单例代码。 We try to get them, if the class exists in our collection we return it otherwise we create it and store it in our collection. 我们尝试获取它们,如果该类存在于我们的集合中,则将其返回,否则我们将其创建并将其存储在我们的集合中。 We use double-checked locking to make sure that we don't sync on every get operation. 我们使用双重检查锁定来确保不对每个get操作进行同步。

However according to alot of article double checked locking is broken. 但是,根据大量文章,再次检查锁定已损坏。 However i don't know if this is the case here, since the map is already initialized and the checking is done on the contains. 但是我不知道这是否是这种情况,因为地图已经初始化并且对包含进行了检查。 What do you guys think? 你们有什么感想? is there anyway to make the double checked locking work here? 无论如何,是否可以在这里进行双重检查锁定?

Map <Class <?>, Object> clazzes = getClazzes ();
T singleton = null;
if (false == clazzes.containsKey (clazz))
{
     synchronized (clazzes)
     {
         if (false == clazzes.containsKey (clazz))
         {
            try
            {
                singleton = clazz.newInstance ();
                clazzes.put (clazz, singleton);
            }
            catch (InstantiationException e)
            {
                 throw new IllegalArgumentException ( "cannot instantiate class " + clazz, e);
            }
            catch (IllegalAccessException e)
            {
                  throw new IllegalArgumentException ("cannot instantiate class " +  clazz, e);
            }
         }
         else
         {
             singleton = clazz.cast (clazzes.get (clazz));
         }
      }
 }

Thanks 谢谢

Ok, so I did some research. 好的,所以我做了一些研究。 According to this document the put operation has a happens-before relation with contains keys. 根据该文档 ,放置操作与包含键之间具有先发生后关系。 Hence if we use a ConcurrentHashMap the double-checked locking should work 因此,如果我们使用ConcurrentHashMap,则双重检查锁定应该起作用

Not to stir the pot unnecessarily, but there are good implementations of this pattern -- something like https://code.google.com/p/guava-libraries/wiki/CachesExplained 不必不必要地搅动锅,但是这种模式有很好的实现方式-类似于https://code.google.com/p/guava-libraries/wiki/CachesExplained

// Construction/setup
LoadingCache<Class<?>, Object> singletons = CacheBuilder.newBuilder()
       .build(
           new CacheLoader<Class<?>, Object>() {
             public Object load(Class<?> key) throws AnyException {
               return key.newInstance();
             }
           });
// client threads
return singletons.get(String.class);

The big advantage of this class over your implementation is that callers block per key, not per map. 与您的实现相比,此类的最大优点是调用者按键而不是按映射阻塞。 So two threads getting two separate singletons can both proceed. 因此,获得两个单独单例的两个线程都可以继续进行。 Two threads getting the same singleton will wait for it to be constructed. 具有相同单例的两个线程将等待其构建。

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

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