目录
谈谈HashMap、Hashtable和ConcurrenHashMap区别
CocurrentHashMap历史变化、数据结构及原理
在并发编程里面使用的CocurrentHashMap,在1.7我们使用sengment分段锁,每一次key进来之后,他都会判断你这个key是属于哪一个分段里面的,从而拿到sengment。锁主要是加在链表上的,因为链表会导致我们线程安全的问题,1.8之后我们将锁改成了CAS+synchronized,解决分段锁的弊端。
为什么1.7到1.8要换一种方式
之所以改锁机制是因为sengment分段锁他可以设置,但是他默认是16段,这个时候我们的并发量就会有一个限制,包括我们需要去估sengment的个数,如果估少了,就会导致锁的空闲,估大了会导致锁的一些竞争,而且一旦初始化以后,它是不可以扩容的,所以之后改成了自旋锁,大大提高了性能。
分段锁是的底层怎么实现的;
分段锁底层维护了一个数组,我们默认的话是16段,每一个段就相当于一把锁,然后最大的并发量可能到达16;
他的继承结构;
它继承了ReentrantLock,然后ReentrantLock继承了AQS(AbstractQueuedSynchronizer)
自旋锁是怎么实现的
思想是给 table的每一个下标都加锁,也就是当对下标进行操作时都会加锁(CAS+Synchronize)。ConcurrentHashMap 成员变量使用 volatile 修饰,免除了指令重排序,同时保证内存可见性,另外使用 CAS操作和 synchronized结合实现赋值操作,多线程操作只会锁住当前操作索引的节点。
如果俩个key都在同一个分段上面,是怎么保证安全的;
CAS的实现原理
CAS其实就是CompareAndSwap首先他会传入一个值还有他的地址,然后进行一个CAS的判断,当前的值与我们现在的值进行比较,如果说一样的话,那我再会进行一个数据的插入,当前的第三个值插入进去,如果不相同从新获取值,然后进行修改,进行插入,这个值可能会有一个ABA的问题,所以每次拿到值以后,会给他加一个版本号,然后进行比较插入的。
谈谈HashMap、Hashtable和ConcurrenHashMap区别
HashMap和Hashtable的区别
它们两个在工作原理上几乎是一样的。它们两个的区别主要体现在:对键值对的要求、线程的安全性,迭代器的选择以及速度上。
1.对键值对的要求
在进行集合的put(key, value)操作时,对于HashMap来说,它允许key和value的值可以是null。但是,Hashtable则对key和value有要求,不允许key和value为null
2.线程的安全上
HashMap是非同步的(synchronized),这也意味着,HashMap在进行插入、删除等操作的时候,是线程不安全的,如果自己没有在程序上对HashMap进行同步的处理,则不能让多个线程共享一个变量。如下图(没有加同步锁)
但,Hashtable是线程安全的,这也意味着可以在多个线程的环境上,共享一个变量。不过,需要提出的是,Hashtable是在每个方法前面加一个锁的。如下图
使用迭代器上的区别
HashMap的迭代器(Iterator)是使用fail-fast机制的(快速失败机制),而Hashtable的迭代器(enumerator)使用的是fail-safe机制(快速安全)。
处理速度上的区别
居然Hashtable在线程安全方面要比HashMap强,那么在其他的方面自然要比它弱。由于Hashtable是线程安全的,同步的,那么在单线程的情况下,它的处理速度是要比HashMap慢的。
但是,就算在多线程环境下,我们也不使用Hashtable,Hashtable的同步锁是加在方法名前面的,意味着它把整个方法的代码都给锁的,所以在处理速度上是特别慢的。所以在多线程的环境下,我们优先使用另一个集合:ConcurrentHashMap,这个集合在工作原理上几乎和前面两个一样,但它是线程安全的,并且它不像Hashtable那样,把整个方法都给加锁,而是在方法里面的关键代码上加同步锁,只会锁住目前所在entry所在的节点。如图:
所以,它在处理速度上比Hashtable要快,但比HashMap慢,可以说,ConcurrentHashMap是HashMap和Hashtable的折中方案。