ConcurrentHashMap类的理解
2015-07-02 15:56
1341 查看
ConcurrentHashMap类的理解
ConcurrentHashMap是java 中支持高并发,高吞吐量的hashMap实现。ConcurrnetHashMap是基于线程安全的一个类。曾看到某个帖子http://blog.sina.com.cn/s/blog_605f5b4f0100qsio.html,在针对于Collections.synchronizedMap、ConcurrentHashMap、Hashtable,进行性能测试。模拟1000个并发,每个测试1000次操作,循环测试100轮,最后读写对应的时间分别为:(6544ms,707ms),(5960ms,650ms),(6719ms,713ms)(此数据依据当前运行条件,有浮动,但是得出的结论是,ConcurrentHashMap比其余两个在读和取上都会快一些)。
锁分离
通过HashMap分析知道,Synchronized是针对整张hash表的,即每次锁住整张表,而ConcurrentHashMap允许多个修改操作并发进行。其关键是采用了锁分离技术。ConCurrentHashMap内部使用段(segment)来表示这些不同的部分,每个段就是一个小的hashtable。但是size()和containsValue(),则可能需要锁住整个表。
Hashmap与ConcurrentHashMap的结构比较
每一个segment管理着一个小的hashtable,所以在多线程下访问ConcurrentHashMap,只需对对应segment进行加锁即可。
ConcurrentHashMap的详细结构
hashEntry在源码中的表示如下,其key,hash,next均为final,为不可变,value为volatile。
意味着:
1.我们的key尽量使用int或者string类型做为key。
2.next为final,不能从hash的中间或者尾部添加或者删除节点,因为这样做需要修改next的引用值。
2.1 对于put操作,新加入的元素,都是放在hash链的链头,
2.2 对于remove操作,是将要删除的前面的所有节点复制一遍,然后,复制后的最后一个节点,指向要删除节点的下一个节点。
3.对于value为volatile类型,每次访问value时,都是去内存中取最新的值。
Segment中的数据结构,
278行出,就是segment对应的hashTable
Put 方法
1.先根据传递过来的key获取其hashcode,然后再hash一次得到segment的hash值。
2.通过segmentFor,寻找到key值对应的segment段。
3.调用segment中的put方法,将对应的值put进入对应的segment的hashtable中。
4.在segment的put方法中
4.1 416行,通过lock给此段加锁
4.2 在423行获取到链头,通过425行的while循环,找到对应的hashentry。
4.3 在437行,如果没有找到,即网链表中新增加一个hashEntery。
4.4 437行的hashEntry的构造函数如上图代码。将新添加的next指向first,然后tab[index]=新添加的HashEntry。就这样将新添加的元素添加到了链表头
Remove
1.Segment寻找方式与put一样
2.真正执行remove的是segment类中的remove方法
3.在514行,执行lock,519行获取链头first。使e指向first。通过512的while循环找到需要删除的HashEntry位置。
4.真正重要在534~536行,此处通过for循环,将要删除的节点前面所有的节点重新复制一遍,在重新设置起next。
例如原来的链表 为1->2->3->4->5 ,如果需删除的节点为4,通过for循环后,链表将变成3->2->1->5.节点前的链表顺序将会倒叙
Get
其寻找方式与put差不多,这里就不再重复。只是这里将锁加载读取value处。。。。。。
这是hashMap下的get方法
在conCureentHashmap中,get,put方法是没有对key进行空判断的。所以在conCureentHashmap是不允许使用null做为key
Size()
在调用size时,会设计到跨段操作。在742~747进行统计的时候,需要分别对每段进行lock。然后获取数据。
ConcurrentHashMap是java 中支持高并发,高吞吐量的hashMap实现。ConcurrnetHashMap是基于线程安全的一个类。曾看到某个帖子http://blog.sina.com.cn/s/blog_605f5b4f0100qsio.html,在针对于Collections.synchronizedMap、ConcurrentHashMap、Hashtable,进行性能测试。模拟1000个并发,每个测试1000次操作,循环测试100轮,最后读写对应的时间分别为:(6544ms,707ms),(5960ms,650ms),(6719ms,713ms)(此数据依据当前运行条件,有浮动,但是得出的结论是,ConcurrentHashMap比其余两个在读和取上都会快一些)。
锁分离
通过HashMap分析知道,Synchronized是针对整张hash表的,即每次锁住整张表,而ConcurrentHashMap允许多个修改操作并发进行。其关键是采用了锁分离技术。ConCurrentHashMap内部使用段(segment)来表示这些不同的部分,每个段就是一个小的hashtable。但是size()和containsValue(),则可能需要锁住整个表。
Hashmap与ConcurrentHashMap的结构比较
每一个segment管理着一个小的hashtable,所以在多线程下访问ConcurrentHashMap,只需对对应segment进行加锁即可。
ConcurrentHashMap的详细结构
hashEntry在源码中的表示如下,其key,hash,next均为final,为不可变,value为volatile。
意味着:
1.我们的key尽量使用int或者string类型做为key。
2.next为final,不能从hash的中间或者尾部添加或者删除节点,因为这样做需要修改next的引用值。
2.1 对于put操作,新加入的元素,都是放在hash链的链头,
2.2 对于remove操作,是将要删除的前面的所有节点复制一遍,然后,复制后的最后一个节点,指向要删除节点的下一个节点。
3.对于value为volatile类型,每次访问value时,都是去内存中取最新的值。
Segment中的数据结构,
278行出,就是segment对应的hashTable
Put 方法
1.先根据传递过来的key获取其hashcode,然后再hash一次得到segment的hash值。
2.通过segmentFor,寻找到key值对应的segment段。
3.调用segment中的put方法,将对应的值put进入对应的segment的hashtable中。
4.在segment的put方法中
4.1 416行,通过lock给此段加锁
4.2 在423行获取到链头,通过425行的while循环,找到对应的hashentry。
4.3 在437行,如果没有找到,即网链表中新增加一个hashEntery。
4.4 437行的hashEntry的构造函数如上图代码。将新添加的next指向first,然后tab[index]=新添加的HashEntry。就这样将新添加的元素添加到了链表头
Remove
1.Segment寻找方式与put一样
2.真正执行remove的是segment类中的remove方法
3.在514行,执行lock,519行获取链头first。使e指向first。通过512的while循环找到需要删除的HashEntry位置。
4.真正重要在534~536行,此处通过for循环,将要删除的节点前面所有的节点重新复制一遍,在重新设置起next。
例如原来的链表 为1->2->3->4->5 ,如果需删除的节点为4,通过for循环后,链表将变成3->2->1->5.节点前的链表顺序将会倒叙
Get
其寻找方式与put差不多,这里就不再重复。只是这里将锁加载读取value处。。。。。。
这是hashMap下的get方法
在conCureentHashmap中,get,put方法是没有对key进行空判断的。所以在conCureentHashmap是不允许使用null做为key
Size()
在调用size时,会设计到跨段操作。在742~747进行统计的时候,需要分别对每段进行lock。然后获取数据。
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法