为什么没有放置带有操作结果的并发哈希图? putIfAbsent 的用例是什么?
Why there is no put on concurrent hashmap with operation outcome? And what's the use case of putIfAbsent?
我深入研究了并发性,并且真的很难理解并发数据结构中使用的一些设计,即并发哈希映射。
有一些我的陈述和加粗的问题,请帮我确认并回答。
putIfAbsent
无法告诉正在执行的线程是它实际上用新值替换了键还是采用了现有的旧值,因为在这两种情况下它都会 return 旧值。那么 'putIfAbsent' 的意义是什么,因为在大多数用例中我们实际上报告结束 client/user/about 操作结果,我知道这可能是概括但仍然如此?我们中的大多数人可能会对 Optional<Entry<K,V>> putIfAbsentAndReturnValueIfPut(K,V)
感到高兴,类似的东西 :-) ?
我从 putIfAbsent
原子性中得到什么? 如果我想为最终用户报告操作结果,我仍然需要使用同步访问。
设想以下结构:
Map<String, Integer> map = new ConcurrentHashMap<>();
Outcome someMethod(String key, Integer value) {
Integer returnedValue = map.putIfAbsent(key, value);// ??? so how do I know if I updated the value?
map.get(key).equals(value); // even if I compare, I am not in synchronized context
}
所以如果我的密钥是 UUID,在很长的 运行 中它可能会为新的映射条目生成重复的密钥,我如何确保如果第二个线程在第一个之后调用 "put" 相同键:
- 一个。操作发生时,线程尝试放置。
- 乙。操作结果
是已知的,所以第二个线程可以尝试重新生成一个新的 UUID 并尝试
重新放置或通知调用者操作失败?
更新:谢谢大家,这是那些日子之一..
您始终可以通过检查 putIfAbsent
的 return 值来了解该值是已添加还是已经存在:
final ConcurrentMap<String,Object> map = new ConcurrentHashMap<>();
final Object old = map.putIfAbsent("hello", "world");
if (old != null) {
// The value was already present and has not been modified
// by the call.
} else {
// There was no prior entry, and "world" has been assigned
// as value for key "hello"
}
请注意,如果地图实现接受 null
作为条目的值,这仍然是不明确的。 (可能)由于这个原因,ConcurrentHashMap
不接受 null
作为键和值:
Like Hashtable but unlike HashMap, this class does not allow null to be used as a key or value.
(如documentation中所述)
"putIfAbsent
无法告诉正在执行的线程它实际上是用新值替换了键还是使用了现有的旧值,因为在这两种情况下它都会 return 旧的价值。”
你真的阅读 putIfAbsent()
? Seems you read the javadoc of put()
的 javadoc 并且 假设 putIfAbsent()
的行为相同。它没有:
If the specified key is not already associated with a value (or is mapped to null) associates it with the given value and returns null
, else returns the current value.
由于 ConcurrentHashMap
不允许 允许 null
用作键或值,您将确定该方法是否添加了值. null
表示已添加值,non-null
表示未添加值,return 值是地图中已有的值。
最终检测结果!!
我深入研究了并发性,并且真的很难理解并发数据结构中使用的一些设计,即并发哈希映射。
有一些我的陈述和加粗的问题,请帮我确认并回答。
putIfAbsent
无法告诉正在执行的线程是它实际上用新值替换了键还是采用了现有的旧值,因为在这两种情况下它都会 return 旧值。那么 'putIfAbsent' 的意义是什么,因为在大多数用例中我们实际上报告结束 client/user/about 操作结果,我知道这可能是概括但仍然如此?我们中的大多数人可能会对 Optional<Entry<K,V>> putIfAbsentAndReturnValueIfPut(K,V)
感到高兴,类似的东西 :-) ?
我从 putIfAbsent
原子性中得到什么? 如果我想为最终用户报告操作结果,我仍然需要使用同步访问。
设想以下结构:
Map<String, Integer> map = new ConcurrentHashMap<>();
Outcome someMethod(String key, Integer value) {
Integer returnedValue = map.putIfAbsent(key, value);// ??? so how do I know if I updated the value?
map.get(key).equals(value); // even if I compare, I am not in synchronized context
}
所以如果我的密钥是 UUID,在很长的 运行 中它可能会为新的映射条目生成重复的密钥,我如何确保如果第二个线程在第一个之后调用 "put" 相同键:
- 一个。操作发生时,线程尝试放置。
- 乙。操作结果 是已知的,所以第二个线程可以尝试重新生成一个新的 UUID 并尝试 重新放置或通知调用者操作失败?
更新:谢谢大家,这是那些日子之一..
您始终可以通过检查 putIfAbsent
的 return 值来了解该值是已添加还是已经存在:
final ConcurrentMap<String,Object> map = new ConcurrentHashMap<>();
final Object old = map.putIfAbsent("hello", "world");
if (old != null) {
// The value was already present and has not been modified
// by the call.
} else {
// There was no prior entry, and "world" has been assigned
// as value for key "hello"
}
请注意,如果地图实现接受 null
作为条目的值,这仍然是不明确的。 (可能)由于这个原因,ConcurrentHashMap
不接受 null
作为键和值:
Like Hashtable but unlike HashMap, this class does not allow null to be used as a key or value.
(如documentation中所述)
"putIfAbsent
无法告诉正在执行的线程它实际上是用新值替换了键还是使用了现有的旧值,因为在这两种情况下它都会 return 旧的价值。”
你真的阅读 putIfAbsent()
? Seems you read the javadoc of put()
的 javadoc 并且 假设 putIfAbsent()
的行为相同。它没有:
If the specified key is not already associated with a value (or is mapped to null) associates it with the given value and returns
null
, else returns the current value.
由于 ConcurrentHashMap
不允许 允许 null
用作键或值,您将确定该方法是否添加了值. null
表示已添加值,non-null
表示未添加值,return 值是地图中已有的值。
最终检测结果!!