使用HashMap进行双重映射

时间:2014-04-28 10:16:19

标签: java synchronization hashmap concurrenthashmap double-checked-locking

我们一直在研究一段代码来获取singeltons。我们尝试获取它们,如果我们的集合中存在类,则返回它,否则我们创建它并将其存储在我们的集合中。我们使用双重检查锁定来确保我们不会在每次获取操作时同步。

然而根据很多文章双重检查锁定被打破。但是我不知道这是否是这种情况,因为地图已经初始化并且对包含进行了检查。你们有什么感想?无论如何要在这里进行双重检查锁定?

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

由于

2 个答案:

答案 0 :(得分:0)

好的,所以我做了一些研究。根据{{​​3}},put操作与包含键有一个before-before关系。因此,如果我们使用ConcurrentHashMap,则双重检查锁定应该起作用

答案 1 :(得分:0)

不要不必要地搅拌锅,但这种模式有很好的实现 - 比如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);

这个类的优势在于你的实现是调用者阻塞每个键,而不是每个映射。因此,获得两个单独的单身的两个线程都可以继续。获得相同单例的两个线程将等待它构建。