繁体   English   中英

Java ConcurrentHashMap原子获取(如果存在)

[英]Java ConcurrentHashMap atomic get if present

如何在并发哈希映射上执行安全获取操作? (与putIfAbsent相同)

不好的例子,不是非常线程安全(检查然后行为情况):

ConcurrentMap<String, SomeObject> concMap = new ...

//... many putIfAbsent and remove operations

public boolean setOption(String id, Object option){
   SomeObject obj = concMap.get(id);

   if (obj != null){
      //what if this key has been removed from the map?
      obj.setOption(option);
      return true;
   }

   // in the meantime a putIfAbsent may have been called on the map and then this
   //setOption call is no longer correct

   return false;
}

另一个糟糕的例子是:

   public boolean setOption(String id, Object option){
       if (concMap.contains(id)){
           concMap.get(id).setOption(option);
           return true;
       }
       return false;
    }

这里需要的是不要通过同步来阻止添加,删除和获取操作。

谢谢

ConcurrentHashMap上的get()方法是原子的。 由于该映射不允许空值,因此get()实现“get if present”:如果结果为null ,则该键不存在。

不要使用containsKey / get ,只需调用get 如果该方法返回null则该键不存在,否则键存在,并且您获得了在get时映射到的值。

来自文档:

返回指定键映射到的值,如果此映射不包含键的映射,则返回null。

这是你的第二个例子应该是这样的:

public boolean setOption(String id, Object option) {

    SomeObject opt = concMap.get(id);
    if (opt == null)
        return false;

    opt.setOption(option);
    return true;
}

您似乎要做的是将密钥锁定在多个操作上。 只有每个操作都是原子的。 这些不是锁定密钥的简单方法,只是锁定地图。

但是在“如果我删除密钥”的情况下,您可以做的就是延迟删除操作,直到调用setOption为止。 结果应该是一样的。

您似乎试图解决可能不需要解决的问题。 您还没有解释为什么在删除密钥后或者等待删除密钥时调用setOption是不好的。

如果需要对ConcurrentMap中的单个键执行多个操作,可以使用Lock striping技术来减少争用,这是Guava框架的一个示例:

   private Striped<Lock> lock;
    public boolean setOption(String id, Object option) {
      try {
        Lock lock = concMap.get(id);
        lock.lock();
          if (concMap.contains(id)){
          concMap.get(id).setOption(option);
       return true;
   }
   return false;
        } finally {
         lock.unlock();
        }
    }

或者,既然Java 8:ConcurrentMap.compute是一个新的原子方法,请查看它是如何在一个键上完成的:

    concMap.compute(keyId, (key, value) -> {
    dosmth; ... return key;  });

ps可能的变化是ConcurrentMap.computeIfPresent()等。

暂无
暂无

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

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