如何在ConcurrentHashMap中基于getOrDefault()实现原子getOrDefaultWithPut()?
How to implement atomic getOrDefaultWithPut() based on getOrDefault() in ConcurrentHashMap?
ConcurrentHashMap supports atomic getOrDefault(Object key, V defaultValue)
,其中
Returns the value to which the specified key is mapped, or the given default value if this map contains no mapping for the key.
我的问题是:
How can I enhance ConcurrentHashMap
by providing an atomic operation, say getOrDefaultWithPut(Object key, V defaultValue)
, which
"Returns the value to which the specified key is mapped, or first put the the given default value into the map and then return the default value if this map contains no mapping for the key.`"
我的解决方案:
目前我有 Wrapper
class 个
private ConcurrentMap<K, V> map = new ConcurrentHashMap<>();
方法是:
public synchronized K getOrDefaultWithPut(K key, V defaultValue)
{
map.putIfAbsent(key, defaultValue);
return map.get(key);
}
- Is this implementation thread-safe?
- Is
synchronized
necessary? What bad would happen if it is removed?
- If
getOrDefaultWithPut(K key, V defaultValue)
is the only public method of Wrapper
, is this implementation thread-safe and is synchronized
necessary?
只需使用computeIfAbsent
If the specified key is not already associated with a value, attempts
to compute its value using the given mapping function and enters it
into this map unless null
. The entire method invocation is performed
atomically [...]
Returns
the current (existing or computed) value associated with the specified key, or null
if the computed value is null
提供一个 mappingFunction
来生成您的默认值,这将满足您的要求。
Returns the value to which the specified key is mapped
这是现有值。
or first put the the given default value into the map and then return the default value if this map contains no mapping for the key
该方法将插入计算值(默认值),如果不是 null
,并且 return 该计算值。
此解决方案不需要 synchronized
。方法调用是原子的,因此是线程安全的。
差不多。您应该使用 putIfAbsent
返回的值,而不是执行另一个 .get
,并且您不需要它 synchronized
(无论如何,在这种情况下它毫无用处,除非所有其他调用者都知道也同步,这违背了 ConcurrentHashMap
:
的目的
public V getOrDefaultWithPut(K key, V defaultValue)
{
V val = map.putIfAbsent(key, defaultValue);
return val == null ? defaultValue : val;
}
Edit: computeIfAbsent
也可以,这只是简单了一点,因为在这种情况下你不需要定义一个函数,而且也是,我认为,作为一个答案,它的信息量更大,因为它实际上用你原来的方法解决了问题,而不是用不同的方法代替它。
ConcurrentHashMap supports atomic getOrDefault(Object key, V defaultValue)
,其中
Returns the value to which the specified key is mapped, or the given default value if this map contains no mapping for the key.
我的问题是:
How can I enhance
ConcurrentHashMap
by providing an atomic operation, saygetOrDefaultWithPut(Object key, V defaultValue)
, which"Returns the value to which the specified key is mapped, or first put the the given default value into the map and then return the default value if this map contains no mapping for the key.`"
我的解决方案:
目前我有 Wrapper
class 个
private ConcurrentMap<K, V> map = new ConcurrentHashMap<>();
方法是:
public synchronized K getOrDefaultWithPut(K key, V defaultValue)
{
map.putIfAbsent(key, defaultValue);
return map.get(key);
}
- Is this implementation thread-safe?
- Is
synchronized
necessary? What bad would happen if it is removed?- If
getOrDefaultWithPut(K key, V defaultValue)
is the only public method ofWrapper
, is this implementation thread-safe and issynchronized
necessary?
只需使用computeIfAbsent
If the specified key is not already associated with a value, attempts to compute its value using the given mapping function and enters it into this map unless
null
. The entire method invocation is performed atomically [...]Returns
the current (existing or computed) value associated with the specified key, or
null
if the computed value isnull
提供一个 mappingFunction
来生成您的默认值,这将满足您的要求。
Returns the value to which the specified key is mapped
这是现有值。
or first put the the given default value into the map and then return the default value if this map contains no mapping for the key
该方法将插入计算值(默认值),如果不是 null
,并且 return 该计算值。
此解决方案不需要 synchronized
。方法调用是原子的,因此是线程安全的。
差不多。您应该使用 putIfAbsent
返回的值,而不是执行另一个 .get
,并且您不需要它 synchronized
(无论如何,在这种情况下它毫无用处,除非所有其他调用者都知道也同步,这违背了 ConcurrentHashMap
:
public V getOrDefaultWithPut(K key, V defaultValue)
{
V val = map.putIfAbsent(key, defaultValue);
return val == null ? defaultValue : val;
}
Edit: computeIfAbsent
也可以,这只是简单了一点,因为在这种情况下你不需要定义一个函数,而且也是,我认为,作为一个答案,它的信息量更大,因为它实际上用你原来的方法解决了问题,而不是用不同的方法代替它。