我是靠谱客的博主 优秀高山,最近开发中收集的这篇文章主要介绍总结:ConcurrentHashMap一、介绍二、JDK1.7中是分段锁的思想三、JDK1.8的实现四、ConcurrentHashMap在迭代时和HashMap的区别,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一、介绍

HashMap是非线程安全的,而Hashtable虽然是性能安全的,但是性能太低。

ConcurrentHashMap 是Java里面同时兼顾性能和线程安全的一个键值对集合。

HashTable 是一个线程安全的类,因为它的所有 public 方法都被 synchronized 修饰,这样就导致了一个问题,就是效率太低。

二、JDK1.7中是分段锁的思想

基于hash定位segment数组的索引

三、JDK1.8的实现

数据结构采用了和HashMap一样的数据结构,即数组 + 链表或数组 + 红黑树

但是安全方面, ConcurrentHashMap通过CAS去保障

四、ConcurrentHashMap在迭代时和HashMap的区别

当一个集合在迭代的时候如果动态的添加或者删除元素,那么就会抛出 Concurrentmodificationexception ,但是在 ConcurrentHashMap 里面却不会,例如如下代码:

public static void main(String[] args) {
Map<String,String> map = new ConcurrentHashMap<String, String>();
map.put("a","a1");
map.put("b","b1");
map.put("c","c1");
map.put("d","d1");
map.put("e","e1");
Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext()){
String it = iterator.next();
if("b".equals(it)){
map.remove("d");
}
System.out.println(it);
}
}
控制台打印如下:
a
b
c
e

而当你把 ConcurrentHashMap 换成 HashMap 的时候,控制台就会抛出一个异常:

Exception in thread "main" a
b
java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1442)
at java.util.HashMap$KeyIterator.next(HashMap.java:1466)
at xyz.somersames.ListTest.main(ListTest.java:22)

原因在于 ConcurrentHashMap next 方法并不会去检查 modCount expectedModCount ,但是会检查下一个节点是不是为空


if ((p = next) == null)
throw new NoSuchElementException();

当我们进行remove的时候, ConcurrentHashMap 会直接通过修改指针的方式来进行移除操作,同样的,也会锁住 数组 的头节点直至移除结束,所以在同一个时刻,只会有一个线程对 当前数组下标的所有节点 进行操作。

但是在 HashMap 里面, next 方法会进行一个check,而remove操作会修改 modCount ,导致 modCount expectedModCount 不相等,所以就会导致
ConcurrentModificationException

稍微修改下代码:

public static void main(String[] args) {
Map<String,String> map = new ConcurrentHashMap<String, String>();
map.put("a","a1");
map.put("b","b1");
map.put("c","c1");
map.put("d","d1");
map.put("e","e1");
Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext()){
if("b".equals(iterator.next())){
map.remove("d");
}
System.out.println(iterator.next());
}
}
控制台打印如下:
b
d
Exception in thread "main" java.util.NoSuchElementException
at java.util.concurrent.ConcurrentHashMap$KeyIterator.next(ConcurrentHashMap.java:3416)
at com.xzh.ssmtest.ListTest.main(ListTest.java:25)

并发下的处理

由于每一个 Node 的首节点都会被 synchronized 修饰,从而将一个元素的新增转化为一个原子操作,同时 Node value next 都是由 volatile 关键字进行修饰,从而可以保证可见性。

参考:

ConcurrentHashMap1.7分段锁原理 

JDK1.8下ConcurrentHashMap的一些理解(一) 

最后

以上就是优秀高山为你收集整理的总结:ConcurrentHashMap一、介绍二、JDK1.7中是分段锁的思想三、JDK1.8的实现四、ConcurrentHashMap在迭代时和HashMap的区别的全部内容,希望文章能够帮你解决总结:ConcurrentHashMap一、介绍二、JDK1.7中是分段锁的思想三、JDK1.8的实现四、ConcurrentHashMap在迭代时和HashMap的区别所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论