20 | 并发容器:都有哪些“坑”需要我们填?
该思维导图由 AI 生成,仅供参考
同步容器及其注意事项
- 深入了解
- 翻译
- 解释
- 总结
Java并发容器包括同步容器和并发容器两大类。同步容器通过synchronized关键字实现线程安全,但性能较差。为提高性能,Java 1.5及之后版本提供了并发容器,包括List、Map、Set和Queue等类型。 同步容器可通过封装非线程安全容器并控制访问路径实现线程安全。Java提供Collections类包装非线程安全容器,如ArrayList、HashSet和HashMap,使其线程安全。然而,组合操作可能引发竞态条件问题,迭代器遍历容器时存在并发问题。 并发容器包括CopyOnWriteArrayList、ConcurrentHashMap、ConcurrentSkipListMap、CopyOnWriteArraySet、ConcurrentSkipListSet等实现类。这些容器通过不同机制实现线程安全和提高性能。例如,CopyOnWriteArrayList通过复制共享变量实现读操作无锁,但不支持迭代器的增删改操作。 总的来说,并发容器提供线程安全,但需注意适用场景、迭代器操作、性能特点等。文章详细介绍了同步容器和并发容器的特点和使用注意事项,对Java并发编程有参考意义。
《Java 并发编程实战》,新⼈⾸单¥59
全部留言(52)
- 最新
- 精选
- 黑白尤文Java7中的HashMap在执行put操作时会涉及到扩容,由于扩容时链表并发操作会造成链表成环,所以可能导致cpu飙升100%。
作者回复: 👍
2019-04-132175 - ykkk88没有理解为什么concurrentskiplistmap比concurrenthashmap性能好
作者回复: 如果key冲突比较大,hashmap还是要靠链表或者tree来解决冲突的,所以O(1)是理想值。同时增删改操作很多也影响hashmap性能。这个也是要看冲突情况。也就是说hashmap的稳定性差,如果很不幸正好偶遇它的稳定性问题,同时又接受不了,就可以尝试skiplistmap,它能保证稳定性,无论你的并发量是多大,也没有key冲突的问题。
2019-04-13692 - 张天屹我理解的hashMap比其它线性容器更容易出问题是因为有扩容操作,存在更多竞态条件,所以如果条件满足时切换可能导致新生成很多数组,甚至可能出现链表闭环,这种情况可以查看堆栈,比如jstack查看会发现方法调用栈一直卡在HashMap的方法。另外上文迭代器遍历不安全是因为hasNext(size)和next()存在的竞态条件吗
作者回复: 👍,不止是存在竞态条件,如果在遍历的时候出现修改操作,直接抛快速失败异常
2019-04-13247 - WolvesLeader个人认为您第二篇内存模型讲的非常棒,,,,,,,,,,
作者回复: 我觉得自己理解起来困难而且对实际工作还有用的就会讲的深入一些,反之我觉得概念或者工具跟正常思维没有冲突,就会讲的简单,甚至略过。毕竟我们只是工具的使用者,首要问题是利用这些工具解决问题。感谢你的认可,我甚至觉得写完第二篇和管程之后就可以收工了,其他所有章节不过就是帮助大家进一步理解,从不同角度理解。
2019-04-13539 - 龙猫java8之前的版本hashmap执行put方法时会有环形链表的风险,java8以后改成了红黑树
作者回复: 👍
2019-04-18334 - CCC老师,用跳表实现的ConcurrentSkipListMap为什么可以做到无锁并发呢
作者回复: 那个跳表就跟字典的索引一样,通过这个索引既能快速定位数据,也能隔离并发(可以并发查看不同页上的字)
2019-04-1321 - LiamLinkedTransferQueue有什么应用场景吗?
作者回复: 实际工作中,为了防止OOM,基本上都使用有界队列,我工作中也没用过LinkedTransferQueue。
2019-04-1319 - QQ怪除了jdk8之前因为并发导致的链表成环的问题还有一种可能是因为jdk8之前hash冲突还是使用的是链表,而jdk8之后使用了红黑树,开始还是生成链表,当链表长度为8时就会转变为红黑树,时间复杂度为O(logn),比链表效果好的多。
作者回复: 是的,底层实现变了,我同事在1.8版本费了好大劲都没重现出来
2019-04-13215 - 罗洲jdk1.8以前的HashMap并发扩容的时候会导致陷入死循环,所以会导致cpu飙升,那么验证猜想我觉得有2种方法: 1.线上查故障,用dump分析线程。 2.用1.8以前的jdk在本地模拟。
作者回复: 👍
2019-04-1314 - Randy留言中很多都提到在JDK1.8以前会存在HashMap的并发情况下resize可能导致死循环问题,其实这个问题在1.8中也存在,并没有因为在1.8中引入了红黑树而规避掉。因为导致问题的原因是resize方法调用了transfer,也就是说是发生在链表的重组过程,跟红黑树没有关系。所以JDK1.8中还是存在这个问题 请宝令老师指正
作者回复: 刚好有篇公众号讲到这个问题,写的非常好。https://mp.weixin.qq.com/s/yxn47A4UcsrORoDJyREEuQ
2019-11-14311