不懂并发?看完就超神!!!Java并发基础(五)

concurrenthashmap

hashtable、vector和collections

底层都是使用synchronized的重量级锁实现的线程安全,性能不如使用轻量级锁的集合类。

而collections使用装饰器模式将原本线程不安全的比如map、list等通过synchronized变为线程安全的,但是其性能任然不好。

hashmap在多线程下的问题

jdk7并发死链
由于jdk7在插入链表时是使用头插法,在扩容时会进行迁移,迁移过程会先记录下old table的e和next,但在多线程下,可能会有另外一个线程完成了扩容,然后改变了引用地址,此时线程接着按照原来的e和next,就会造成环链。

虽然在JDK8采用了尾插法避免了环链问题,但是在多线程下任然有其他并发问题,在并发下必须使用concurrenthashmap。

源码

构造器

实现lazy loading,concurrenthashmap的长度永远是2^n,所以就算指定initialcapacity为8,最后创建的任是16。
在这里插入图片描述
get
tabat根据bukect下标去寻找链表,hash码为负,表示可能fowarding node或者是红黑树节点。
在这里插入图片描述
put
在这里插入图片描述
concurrent不允许使用null作为key和value。

在这里插入图片描述
通过使用CAS保证table的初始化,只有第一个线程初始化一次。
在这里插入图片描述
表示头节点没有被占用时就创建占用,否则进行下轮循环。
在这里插入图片描述
桶下标冲突,将bucket的头节点使用syn锁住,fh>0表示是普通链表,fh<0表示是红黑树。
在这里插入图片描述
在这里插入图片描述
完成插入后释放头节点锁,检查是否要树化。
在这里插入图片描述
initialTable

sizeCtl为-1表示正在创建,就调用yeild。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/TheCarol/article/details/113050898