我有一个关于Map内对象同步的问题(稍后我更改其值的相同对象)。我想自动读取,检查并可能对地图中的值进行更新,而无需锁定整个地图。这是处理对象同步的有效方法吗?
private final Map<String, AtomicInteger> valueMap = new HashMap<>();
public Response addValue(@NotNull String key, @NotNull Integer value) {
AtomicInteger currentValue = valueMap.get(key);
if (currentValue == null) {
synchronized (valueMap) {
// Doublecheck that value hasn't been changed before entering synchronized
currentValue = valueMap.get(key);
if (currentValue == null) {
currentValue = new AtomicInteger(0);
valueMap.put(key, currentValue);
}
}
}
synchronized (valueMap.get(key)) {
// Check that value hasn't been changed when changing synchronized blocks
currentValue = valueMap.get(key);
if (currentValue.get() + value > MAX_LIMIT) {
return OVERFLOW;
}
currentValue.addAndGet(value);
return OK;
}
}
我没有看到您的方法与标准ConcurrentHashMap的方法有很大的不同-从ConcurrentHashMap
经过大量测试的事实出发,可以将其配置为使用所需确切数量的线程来以最小的开销进行配置。
在ConcurrentHashMap
,你可以使用替代(K key, V old, V new)
方法以原子更新key
到new
只有当old
值没有改变。
由于消除了所有这些AtomicIntegers
而节省的空间,以及由于同步开销较低而节省的时间,可能会补偿必须将replace(k, old, new)
调用包装在while循环内的情况:
ConcurrentHashMap<String, Integer> valueMap =
new ConcurrentHashMap<>(16, .75f, expectedConcurrentThreadCount);
public Response addToKey(@NotNull String key, @NotNull Integer value) {
if (value > MAX_LIMIT) {
// probably should set value to MAX_LIMIT-1 before failing
return OVERFLOW;
}
boolean updated = false;
do {
Integer old = putIfAbsent(key, value);
if (old == null) {
// it was absent, and now it has been updated to value: ok
updated = true;
} else if (old + value > MAX_LIMIT) {
// probably should set value to MAX_LIMIT-1 before failing
return OVERFLOW;
} else {
updated = valueMap.replace(key, old, old+value);
}
} while (! updated);
return OK;
}
同样,从好的方面来说,即使在检查密钥后将其删除,此代码也可以工作(在这种情况下,您会抛出NPE)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句