我想讨论我对并发映射的特定用途,以检测我的逻辑......
如果我用过ConcurrentHashMap
,我可以做熟悉的
private final ConcurrentHashMap<K, V> map = new ConcurrentHashMap<K, V>();
public V getExampleOne(K key) {
map.putIfAbsent(key, new Object());
return map.get(key);
}
但我意识到存在竞争条件putIfAbsent
,如果我从和之间的映射中删除项目get
,上面的方法将返回集合中不再存在的东西。这可能会也可能不会,但是让我们假设对于我的用例来说,这是不行的。
我真正想要的是让整个事情都是原子的。所以,
public V getExampleTwo(K key) {
return map.putIfAbsent(key, new Object());
}
但随着这扩展到
if (!map.containsKey(key))
return map.put(key, value); [1]
return map.get(key);
which for line [1] 将返回null
第一次使用(即,map.put
将返回前一个值,第一次使用是null
)。
在这种情况下,我不能让它返回 null
这给我留下了类似的东西;
public V getExampleThree(K key) {
Object object = new Object();
V value = locks.putIfAbsent(key, object);
if (value == null)
return object;
return value;
}
所以,最后,我的问题;上面的例子在语义上有何不同?是否getExampleThree
确保原子性,getExampleTwo
但正确避免 null 返回?还有其他问题getExampleThree
吗?
我希望围绕选择进行一些讨论。我意识到我可以在调用我的方法的客户端和从地图中删除的方法周围使用非ConcurrentHashMap
和同步,get
但这似乎违背了 ConcurrentHashMap 的目的(非阻塞性质)。这是我保持数据准确的唯一选择吗?
我想这就是您选择 ConcurrentHashMap 的部分原因;在您与之交互时它是可见的/最新的/准确的,但是如果旧数据将成为问题,则可能会进一步产生影响......