![](/img/trans.png)
[英]Atomically searchKeys() and put() in a 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.