JAVA:多线程

HashTable

使用Synchronize锁住整个表,效率比较低。
底层采用数组+链表的结构,冲突处理的方式为链队;
若tab[index]==null,直接插入;否则查找链表如果key相等应该更新value;否则头插;
初始容量11,加载因子0.75
Hashtable扩容的数组长度是旧数组长度乘以2加1;

CocurrentHashMap

与HashTable相比,他用了粒度更小的锁

  • JDK1.7中,CocurrentHashMap实现的数据结构是分段数组+链表的形式,也就是他不会想HashTable那样把整个表锁住,他的内部有Segment分段锁,每次写都只会锁某个Segment区域,所以CocurrentHashMap的并发能力和Seement区域的个数有很大关系。
  • JDK1.8中,CocurrentHashMap的数据结构和HashMap一样,不过和1.7不一样的他是采用内置的Synchronize锁,粒度比1.7更小的。
  • 两个版本的get操作都无需加锁,所以并发程度比较高

ConcurrentHashMap的put()和get()的工作流程是怎样的?
存储对象时,将key和vaule传给put()方法:

  • 如果没有初始化,就调用initTable()方法对数组进行初始化;
  • 如果没有hash冲突则直接通过CAS进行无锁插入;
  • 如果需要扩容,就先进行扩容,扩容为原来的两倍;
  • 如果存在hash冲突,就通过加锁的方式进行插入,从而保证线程安全。(如果是链表就按照尾插法插入,如果是红黑树就按照红黑树的数据结构进行插入);
  • 如果达到链表转红黑树条件,就将链表转为红黑树;
  • 如果插入成功就调用addCount()方法进行计数并且检查是否需要扩容;

获取对象时,将key传给get()方法:

  • 计算hash值,定位table索引位置,如果头节点符合条件则直接返回key对应的value;
  • 如果遇到正在扩容或者是红黑树结构(eh<0),则调用标记正在扩容的节点,查找该节点,匹配就返回;
  • 链表结构,按照链表查找的方式get;

ConcurrentHashMap中变量使用final和volatile修饰有什么用呢?
使用final关键字修饰变量可以让原本一直保持不变的变量变为常量,可以保证不修改这个值,提高多线程的安全性。
volatile修饰变量主要还是利用了他的可见性,也就是一旦值改变了,其他线程可以马上这个这个变化,这个对于get方法是很重要的。
ConcurrentHashMap有什么缺陷吗?
严格来说读取操作不能保证反映最近的更新。例如线程A调用putAll写入大量数据,期间线程B调用get,则只能get到目前为止已经顺利插入的部分数据。
ConcurrentHashMap中的key和value可以为null吗?为什么?
不能。比如在这种情况下,key不为null,val为null,然后调用get方法,那么返回一定是null。这时就无法区分两种情况:

  • ConcurrentHashMap根本不存在这个key
  • ConcurrentHashMap存在这个key,但是value是null

为什么区分不了?
假设有一个key没有在map中映射过,也就是map中不存在这个key,此时我们调用ConcurrentHashMap.containsKey(key)方法去做一个判断,我们期望的返回结果是false。但是恰好在A线程get(key)之后,调用constainsKey(key)方法之前B线程执行了ConcurrentHashMap.put(key,null),那么当A线程执行完containsKey(key)方法之后我们得到的结果是true,与我们预期的结果就不相符了。
oncurrentHashMap的并发度是什么?
程序在运行时能够同时更新ConcurrentHashMap且不产生锁竞争的最大线程数默认是16,这个值可以在构造函数中设置。如果自己设置了并发度,ConcurrentHashMap会使用大于等于该值的最小的2的幂指数作为实际并发度,也就是比如你设置的值是17,那么实际并发度是32。

CAS

CAS操作包括了3个操作数:

  1. 需要读写的内存位置(V)
  2. 进行比较的预期值(A)
  3. 拟写入的新值(B)

CAS操作逻辑如下:
如果内存位置V的值等于预期的A值,则将该位置更新为新值B,否则不进行任何操作。
许多CAS的操作是自旋的:如果操作不成功,会一直重试,直到操作成功为止。
这里引出一个新的问题,既然CAS包含了Compare和Swap两个操作,它又如何保证原子性呢?
答案是:CAS是由CPU支持的原子操作,其原子性是在硬件层面进行保证的。

ABA问题

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值