多线程学习——并发容器

多线程学习——并发容器

Scroll Down

多线程学习——并发容器

1.并发容器概览

ConcurrentHashMap:线程安全的map
CopyOnWriteArrayList: 线程安全的list
BlockingQueue:阻塞队列
ConcurrentLinkedQueue:高效的非阻塞队列 线程安装的linkelist
CoucurrentSkipListMap:使用跳表数据结构的map
Vector:基本所有方法被synchronized的list 性能低
Hashtable:基本所有方法被synchronized的hashmap
Colletions.synchronizedMap:相比于Hashtable使用的是同步代码块
Colletions.synchronizedList:相比于Vector使用的是同步代码块

2.ConcurrentHashMap

1.Map

image.png
HashMap:使用hash算法存储key-value数据 查询快 线程不安全 可以键存储空值
1.7:
image.png
1.8:
image.png
image.png
Hashtable:基本所有方法被synchronized的hashmap
LinkedMap:保持插入的顺序与存放的顺序一致的Map
Treemap:可以给键进行排序

2.HashMap线程多并发的问题和原因

1.HashMap的put在高并发情况下会导致覆盖(即key的hash值可能一样 将值覆盖)
2.HashMap的put扩容导致数据覆盖
3.HashMap 死循环导致CPU100%:多线程在同时扩容的时候 会造成链表环形链表(你指向我,我指向你)
https://coolshell.cn/articles/9703.html

3.ConcurrentHashMap

1.7的ConcurrentHashMap是由16个segment组成,每个segment里面与hashMap类似,仍然是数组加链表的拉链法,每个segment独立的ReentrantLock锁,每个segment互不影响,提高了并发效率,是分段锁
1.8的ConcurrentHashMap是由node加链表或者红黑树,采用CAS保证并发安全,查询效率变快
image.png
image.png
image.png
put方法是指调用的是putVal()方法其中putVal流程:

1.先判断key value不为空
2.计算hash值
3.根据对应的位置节点的类型,来赋值,或者转换,或者增长链表,或者给红黑树增加节点
4.检查是否满足阈值就红黑化
5.返回oldval

image.png
get流程:

1.计算hash值
2.找到对应的位置,根据情况进行:
	1.直接取值
	2.红黑树取值
	3.遍历链表取值
3.返回结果值

为什么要到8的时候采用红黑树?
默认是链表存储,占用内存更少,想要达到8的概率很低,达到8的时候转换为红黑树可以保证查询效率
使用ConcurrentHashMap要注意使用时的线程安全问题

3.CopyOnWriteArrayList

适应场景:读操作可以尽可能快,而写即使慢一点也没有关系
原理:他是创建新副本,读写分离,即读的是就数据 写的是新数据,迭代的时候数据与创建的数据相同
缺点:数据一致性问题,不能保证数据一致性;内存占用,同时存有两份数据
读写规则:读写可以,读读可以,写写互斥

祝君好梦!