ConcurrentHashMap实现原理
来源:互联网 发布:tomcat启动显示端口号 编辑:程序博客网 时间:2024/05/17 01:09
集合是编程中最常用的数据结构。而谈到并发,几乎总是离不开集合这类高级数据结构的支持。比如两个线程需要同时访问一个中间临界区(Queue),比如常会用缓存作为外部文件的副本(HashMap)。这篇文章主要分析jdk1.5的3种并发集合类型(concurrent,copyonright,queue)中的ConcurrentHashMap,让我们从原理上细致的了解它们,能够让我们在深度项目开发中获益非浅。
return readValueUnderLock(e)到底是用来干什么的呢?研究它的代码,在锁定之后返回一个值。但这里已经有一句V v = e.value得到了节点的值,这句return readValueUnderLock(e)是否多此一举?事实上,这里完全是为了并发考虑的,这里当v为空时,可能是一个线程正在改变节点,而之前的get操作都未进行锁定,根据bernstein条件,读后写或写后读都会引起数据的不一致,所以这里要对这个e重新上锁再读一遍,以保证得到的是正确值,这里不得不佩服Doug Lee思维的严密性。整个get操作只有很少的情况会锁定,相对于之前的Hashtable,并发是不可避免的啊!
V get(Object key, int hash) { if (count != 0) { // read-volatile HashEntry e = getFirst(hash); while (e != null) { if (e.hash == hash && key.equals(e.key)) { V v = e.value; if (v != null) return v; return readValueUnderLock(e); // recheck } e = e.next; } } return null; }
V readValueUnderLock(HashEntry e) { lock(); try { return e.value; } finally { unlock(); } }
V put(K key, int hash, V value, boolean onlyIfAbsent) { lock(); try { int c = count; if (c++ > threshold) // ensure capacity rehash(); HashEntry[] tab = table; int index = hash & (tab.length - 1); HashEntry first = (HashEntry) tab[index]; HashEntry e = first; while (e != null && (e.hash != hash || !key.equals(e.key))) e = e.next; V oldValue; if (e != null) { oldValue = e.value; if (!onlyIfAbsent) e.value = value; } else { oldValue = null; ++modCount; tab[index] = new HashEntry(key, hash, first, value); count = c; // write-volatile } return oldValue; } finally { unlock(); } }
V remove(Object key, int hash, Object value) { lock(); try { int c = count - 1; HashEntry[] tab = table; int index = hash & (tab.length - 1); HashEntry first = (HashEntry)tab[index]; HashEntry e = first; while (e != null && (e.hash != hash || !key.equals(e.key))) e = e.next; V oldValue = null; if (e != null) { V v = e.value; if (value == null || value.equals(v)) { oldValue = v; // All entries following removed node can stay // in list, but all preceding ones need to be // cloned. ++modCount; HashEntry newFirst = e.next; for (HashEntry p = first; p != e; p = p.next) newFirst = new HashEntry(p.key, p.hash, newFirst, p.value); tab[index] = newFirst; count = c; // write-volatile } } return oldValue; } finally { unlock(); } }
static final class HashEntry { final K key; final int hash; volatile V value; final HashEntry next; HashEntry(K key, int hash, HashEntry next, V value) { this.key = key; this.hash = hash; this.next = next; this.value = value; } }
0 0
- ConcurrentHashMap实现原理
- ConcurrentHashMap之实现原理
- ConcurrentHashMap实现原理
- ConcurrentHashMap实现原理
- ConcurrentHashMap实现原理
- ConcurrentHashMap 的实现原理
- ConcurrentHashMap实现原理
- ConcurrentHashMap实现原理
- ConcurrentHashMap实现原理
- ConcurrentHashMap 的实现原理
- ConcurrentHashMap实现原理--上
- ConcurrentHashMap实现原理--中
- ConcurrentHashMap的实现原理
- ConcurrentHashmap实现原理?
- ConcurrentHashmap实现原理
- ConcurrentHashMap的实现原理
- ConcurrentHashMap的实现原理
- ConcurrentHashMap实现原理分析
- 小知识点集锦
- ios8新特性widget开发(手机上和通知栏并列的今天的制作)
- Spring 事务学习笔记(1):事务的基本知识
- UITextField 解决限制文字长度不准确的问题
- adb 在ubuntu上的一个坑
- ConcurrentHashMap实现原理
- 使用Matplotlib制作动图
- 在ubuntu15.04上安装Android Studio过程记录
- nginx中配置跨域支持功能
- App Widget
- 按键精灵
- canvas如何把图像绘制到准确位置
- AIDL的Binder框架
- 【OJ 高级】扑克牌大小