我的疑问很简单。根据其他帖子,由于读+写操作 count++,这不是线程安全的。但据我所知,计算会阻止地图内该键的整个扇区。所以两个线程不可能同时执行这个操作。为什么我应该使用原子整数或任何其他并发对象?
密钥可以是一个配置文件,而计数器只是一个可以是数字的计数器。帖子、消息、点赞...
该结构是一个 ConcurrentHashMap
counters.compute(key, (key, counter) -> {
if (counter == null) {
return 1;
} else {
return count++;
}
});
我在某些测试中没有发现执行线程有任何问题。但我仍然不明白为什么要使用原子整数。
你的例子是有缺陷的,因为
return count++;
增加 count
但返回之前的值 - 即它永远不会累加。该行应该是 return count + 1;
:
counters.compute(key, (k, count) -> {
if (count == null) {
return 1;
} else {
return count+1;
}
});
请注意,
ConcurrentHashMap.compute()
(以 Integer
作为值)的这种用法本质上是线程安全的:
compute()
函数针对特定键以原子方式执行 - 即没有其他线程可以同时为同一键调用compute()
,因此您不能丢失更新。get()
调用要么看到旧值,要么看到新值,具体取决于确切的时间,但(因为 Integer
是不可变的)它们不能破坏计数。