@chenxuxiong
2016-05-26T15:42:17.000000Z
字数 1023
阅读 1411
JAVA基础
为什么支持多线程?
ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术。读的时候不加锁,写的时候加锁
在ConcurrentHashMap中,就是把Map分成了N个Segment,put和get的时候,都是现根据key.hashCode()算出放到哪个Segment中。当一个线程对其中一个段进行访问时,其他线程仍然可以访问到其他段,默认的情况下是分为16个段。那么在插入的时候效率就能够提升16(n)倍了。具体可以理解为把一个大的Map拆分成N个小的HashTable,根据key.hashCode()来决定把key放到哪个HashTable中。
(1)计算hash
(2)确定元素要存在哪个段里面
(3)获得相应段的锁
(4)插入元素
(5)释放相应的锁
有些方法需要跨段,比如size()和containsValue(),它们可能需要锁定整个表而而不仅仅是某个段,这需要按顺序锁定所有段,操作完毕后,又按顺序释放所有段的锁。这里“按顺序”是很重要的,否则极有可能出现死锁,在ConcurrentHashMap内部,段数组是final的,并且其成员变量实际上也是final的,但是,仅仅是将数组声明为final的并不保证数组成员也是final的,这需要实现上的保证。这可以确保不会出现死锁,因为获得锁的顺序是固定的。
ConcurrentHashMap和Hashtable主要区别就是围绕着锁的粒度以及如何锁,可以简单理解成把一个大的HashTable分解成多个,形成了锁分离
ConcurrentHashMap中主要实体类就是三个:ConcurrentHashMap(整个Hash表),Segment(桶),HashEntry(节点),对应上面的图可以看出之间的关系