ConcurrentHashMap 复合操作下丢失原子性

ConcurrentHashMap 复合操作下丢失原子性

ConcurrentHashMap的线程安全性

ConcurrentHashMap 的线程安全性主要体现在以下几个方面:

  1. 分段锁:在Java 7及之前的版本中, ConcurrentHashMap 通过分段锁(segment locking)技术来提高并发访问的效率。它将数据分成一段一段的存储,每一段数据拥有自己的锁。当一个线程访问一段数据时,只需获取那一段的锁,这样多个线程可以同时访问不同段的数据,从而提高并发性能。

  2. CAS操作:从Java 8开始, ConcurrentHashMap 的实现改进为使用CAS(Compare-And-Swap)操作和synchronized关键字来管理内部结构的并发修改,摒弃了原有的分段锁。这种方法在不牺牲太多性能的同时,简化了代码和内部结构。

原子性的局限

虽然 ConcurrentHashMap 提供了操作的线程安全性,但它并不保证复合操作的原子性。例如,以下操作不是原子的:

map.put(key, map.get(key) + 1);

在这个操作中, map.get(key) 和 map.put(key, value) 分别是线程安全的,但是从 get 取值到 put 存回的过程中间,其他线程可能已经修改了这个key对应的值。这就是所谓的“检查后执行”操作,它需要外部同步来保证整个过程的原子性。

解决方案

为了保证复合操作的原子性,可以使用如下方法:

  • 使用 ConcurrentHashMap 的 compute 方法
    ConcurrentHashMap 提供了一些原子性保证的复合操作,如 compute 、 merge 等。这些方法可以用来原子地修改映射中的值。
concurrentMap
	.compute(key, (k, v) -> 
		(v == null) ? 1 : v + 1);

这个例子中, compute 方法会原子地更新键对应的值,这是通过内部锁定或其他形式的并发控制来实现的。

总结来说, ConcurrentHashMap 确实是线程安全的,但线程安全不等同于原子性。对于复合操作,需要使用适当的方法来确保操作的原子性。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值