【问题标题】:Double mapping with HashMap使用 HashMap 进行双重映射
【发布时间】:2014-04-28 10:16:19
【问题描述】:

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

但是,根据很多文章,双重检查锁定已被破坏。但是我不知道这里是否是这种情况,因为地图已经初始化并且对包含进行了检查。你们有什么感想?有没有办法让双重检查锁定在这里工作?

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

谢谢

【问题讨论】:

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


    【解决方案1】:

    好的,所以我做了一些研究。根据this document,put 操作与 contains 键具有发生前的关系。因此,如果我们使用 ConcurrentHashMap,双重检查锁定应该可以工作

    【讨论】:

    • 感谢您的研究,我们不知道 getClazzes 返回什么。但即使我们假设它返回 HashMap,这里第二个 containsKey 在安全环境中被调用,所以即使我们使用 HashMap,我相信这段代码是线程安全的。
    • getClazzes 返回一个 HashMap
    【解决方案2】:

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

    与您的实现相比,此类的最大优势在于调用者会按键而不是按映射阻塞。因此,获得两个单独的单例的两个线程都可以继续进行。获得相同单例的两个线程将等待它被构造。

    【讨论】:

    • 谢谢,下次设计会议时我会提出来
    猜你喜欢
    • 2018-10-12
    • 2021-09-13
    • 2012-11-09
    • 2016-03-23
    • 1970-01-01
    • 2011-04-24
    • 1970-01-01
    • 2013-04-25
    • 2016-10-13
    相关资源
    最近更新 更多