繁体   English   中英

Java ConcurrentHashMap 原子地获取和放置

[英]Java ConcurrentHashMap Get and Put Atomically

我有一个 ConcurrentHashMap,我想保证 .get 和 .put 操作是原子的。

根据我的分析,计算在这里不是我的选择,因为我必须在 else 块中做一些重要的事情。 知道我怎么能做到这一点吗?

这是代码 - 如果您需要更多信息,请告诉我

private Map<String, Long> ids = new ConcurrentHashMap<>();
ids.putIfAbsent(mapKey, 0L);
Long newId = generateId(mapKey);
if (newId > ids.get(mapKey)) {
   ids.put(mapKey, newId);
   return newId;
} else {
   // do something else
}

您可以将Map与AtomicLong结合使用:Map可以通过每个mapKey获得一个AtomicLong,然后在AtomicLong上进行compareAndSet以获得所需的原子性。

private Map<String, AtomicLong> ids = new ConcurrentHashMap<>();
ids.putIfAbsent(mapKey, new AtomicLong());
AtomicLong idForKey = ids.get(mapKey);
// Optionally, those two lines can be shorted to:
//   ids.computeIfAbsent(mapKey, k -> new AtomicLong())

long newId = generateId(mapKey);
long origId = idForKey.get();
if (newId > origId && idForKey.compareAndSet(origId, newId)) {
   return newId;
} else {
   // do something else
}

这样可以确保仅在能够安装严格增加的ID的情况下才返回newId。 如果有人在您之前(特别是在idForKey.get()compareAndSet之间idForKey.get()进入,那么您仍然会生成newId ,但是您将不会使用update AtomicLong,并且将// do something else阻止。

你可以做这样的事情

private Map<String, Long> ids = new ConcurrentHashMap<>();
private Lock lock = new ReentrantLock();

public Long safeGet(String key) {
    Long value = null;
    try {
        lock.lock();
        value = ids.get(key);
    } catch (final Throwable t) {
    } finally {
        lock.unlock();
        return value;
    }
}

public void safePut(String key, Long value) {
    try {
        lock.lock();
        ids.put(key, value);
    } catch (final Throwable t) {
    } finally {
        lock.unlock();
    }
}

将您的逻辑放入synchronized方法中:

private Map<String, Long> ids = new ConcurrentHashMap<>();
ids.putIfAbsent(mapKey, 0L);
Long newId = generateId(mapKey);

return doSomething();

private synchronized Long doSomething() {
  if (newId > lastEmittedNodeIds.get(mapKey)) {
     ids.put(mapKey, newId);
     return newId;
  } else {
     // do something else
  }
}

暂无
暂无

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

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