多线程(32)并发集合

并发集合是为了解决多线程环境中数据结构安全访问而设计的。在传统的集合如 ArrayListHashMap 等中,当多个线程尝试并发地修改同一个集合时,往往会遇到并发修改异常(ConcurrentModificationException)或者遇到不一致的状态,因为这些集合不是线程安全的。

Java中的并发集合

Java的 java.util.concurrent 包提供了一系列的并发集合,它们能够在多线程环境下安全地执行插入、移除和访问操作。这些集合包括:

  • ConcurrentHashMap
  • CopyOnWriteArrayList
  • CopyOnWriteArraySet
  • ConcurrentLinkedQueue
  • ConcurrentLinkedDeque
  • BlockingQueue 的不同实现,如 ArrayBlockingQueueLinkedBlockingQueuePriorityBlockingQueue
  • BlockingDeque 的实现,如 LinkedBlockingDeque
  • ConcurrentSkipListMapConcurrentSkipListSet

工作原理

1. 分段锁(Segmentation)

ConcurrentHashMap 在Java 7及以前的版本中使用分段锁的概念。集合被分成一系列的段(segment),每个段其实就是一个小的哈希表,并且每个段都有它自己的锁。当一个线程访问一个段时,它只需要获取对应段的锁,而不会影响到其他段。这种方式减少了锁的竞争,使得多个线程可以同时访问不同段的数据。

从Java 8开始,ConcurrentHashMap 使用了一种不同的锁机制来进一步优化性能,具体来说是使用了一种称为CAS(Compare-And-Swap)的技术来减少锁的使用。

2. CAS(Compare-And-Swap)

CAS操作是一种无锁的原子操作,它包含三个操作数------内存位置、预期原值以及新值。CAS操作仅在内存位置的当前值与预期原值相匹配时,才会将内存位置的值更新为新值。这保证了该操作的原子性。AtomicInteger 是 Java 中使用 CAS 的一个例子。

ConcurrentHashMap 中,这种技术被用来实现非阻塞的算法,使得多线程可以在没有锁的情况下安全地执行复杂的更新操作。

3. 写时复制(Copy-On-Write)

CopyOnWriteArrayListCopyOnWriteArraySet 使用了写时复制策略。当集合被修改时,内部结构(如数组)会被整体复制,在副本上进行更改,然后再将原始结构指向新的副本。这种机制确保了在遍历集合时不会抛出 ConcurrentModificationException,因为遍历操作只会访问到原始数据,即使在遍历时有其他线程对集合进行了修改。

写时复制是一种读优化策略,适用于读多写少的并发场景。它的缺点是写操作的成本较高,因为每次修改都需要复制整个底层数组。

4. 阻塞和非阻塞的队列

BlockingQueueBlockingDeque 接口提供了阻塞的插入和移除操作。如果队列为空,取操作会阻塞直到有元素可取;如果队列满了,插入操作会阻塞直到队列有空间。这些集合通常用于生产者-消费者模式。

ConcurrentLinkedQueueConcurrentLinkedDeque 是基于链接节点的线程安全队列,它们使用非阻塞算法,通常通过CAS操作来保证线程安全。

5. 跳表

ConcurrentSkipListMapConcurrentSkipListSet 是基于跳表数据结构的并发集合。跳表是一个有序的数据结构,通常通过多层链表来实现,能够提供与平衡树相当的并发性能,但是实现起来更为简单。跳表允许并发地进行查找、插入和删除操作,其性能通常是对数级别的。

使用场景

这些并发集合的使用依赖于具体的应用场景。如果需要大量的并行读取和少量的更新操作,CopyOnWriteArrayList 可能是最佳选择。而需要高并发插入和删除操作时,ConcurrentLinkedQueueConcurrentLinkedDeque 可能更适合。ConcurrentHashMap 则适用于需要高并发访问和更新的键值对集合。

总之,并发集合通过使用分段锁、CAS、写时复制等高级并发控制技术,提供了在多线程环境中安全且高效的数据操作方式。开发者应当根据具体的并发需求,选择最合适的集合类型来使用。

相关推荐
用户21411832636029 分钟前
Claude Skills 新玩法:用 skill-creator 10 分钟搞定 Excel 报表自动化,职场人必学
后端
東雪木32 分钟前
Spring Boot 2.x 集成 Knife4j (OpenAPI 3) 完整操作指南
java·spring boot·后端·swagger·knife4j·java异常处理
天使街23号43 分钟前
go-dongle v1.2.0 发布,新增 SM2 非对称椭圆曲线加密算法支持
开发语言·后端·golang
用户69371750013842 小时前
Kotlin 协程基础入门系列:从概念到实战
android·后端·kotlin
Moonbit2 小时前
MoonBit Pearls Vol.14:哈希表避坑指南
后端·算法·编程语言
Moonbit2 小时前
MoonBit Pearls Vol.13: 使用 MoonBit 开发一个 HTTP 文件服务器
服务器·后端·http
一 乐2 小时前
个人博客|博客app|基于Springboot+微信小程序的个人博客app系统设计与实现(源码+数据库+文档)
java·前端·数据库·spring boot·后端·小程序·论文
LucianaiB3 小时前
Qoder 降价,立即生效!首购 2 美金/月
后端
微学网络3 小时前
基于 PVE 8.1 的 CentOS / Ubuntu / Docker / Kubernetes 部署手册
后端
Main121383 小时前
JDK 8 Stream API 教程文档
后端