Sto*_*ika 6 concurrency concurrenthashmap java-8
我一直在尝试理解JDK8中的ConcurrentHashMap函数,与JDK7中的它是如何形成对比的(除了源代码之外,还可以找到很好的解释,例如Richard http:// www .burnison.ca/articles/the-concurrent-of-concurrenthashmap).它看起来在JDK8中已经发生了相当大的变化 - 例如,本身没有更多的"段",但不知怎的,我觉得这些变化是为了让代码变得更简单?
我很难理解方法ConcurrentHashMap.putVal(...),特别是以下部分 - 这个直接锁定在'segment'列表的头部,无论如何要插入else {}?:
else if ((fh = f.hash) == MOVED)
tab = helpTransfer(tab, f);
else {//...}
Run Code Online (Sandbox Code Playgroud)对ConcurrentHashMap.casTabAt(...)的代码也不太确定.
另外,关于JDK8中ConcurrentHashMap.get(Object key)的源代码,它是否完全没有锁定(我没有看到任何内容,如果是这样的话,没有锁定它是如何工作的,因为我看不到循环'再试一次?或者还有一些我没有观察到的乐观锁定?
感谢是否有人可以提供一些提示.
关于putVal(K key, V value, boolean onlyIfAbsent)方法
每个bin/bucket包含一个hash字段,它以非常聪明的方式结合了两个目的:
这个部分
else if ((fh = f.hash) == MOVED)
tab = helpTransfer(tab, f);
else {//...}
Run Code Online (Sandbox Code Playgroud)
是在发现地图不为空并且您尝试映射的键的bin不为空之后的第一次检查.
如果您找到的垃圾箱是特殊类型的垃圾箱之一 - 转发箱,则会感到满意.转发箱是必需的,因为调整大小是同时并且迭代地完成并且已经转移(到新表),条目仍然需要可访问(通过旧表中的转发箱).
关于casTabAt((Node<K,V>[] tab, int i, Node<K,V> c, Node<K,V> v)方法
该casTabAt()方法用于使用对象引用的比较和交换操作以原子方式设置映射条目.您仍然可以在几乎所有使用的地方看到典型的CAS循环casTabAt()- 您构建要放置的对象,然后尝试将CAS放在合适的位置.如果在CAS尝试之前复杂的结构感觉很奇怪,你可以看一下Jeff Preshing的你可以做任何一种原子读 - 修改 - 写操作.
从某种意义上说,ConcurrentHashMap仍然使用条带锁定,但具有更精细的锁定粒度(竞争区域现在从多仓区段最小化到单个区间)并且锁几乎完全被CAS操作取代.
关于get(Object key)方法
该get()方法可以在没有任何锁定的情况下离开,因为在大多数情况下,使用volatile语义(通过上述casTabAt()方法和相关tabAt()方法)来设置和检索bin内容.如果bin包含映射到同一bin的红黑树条目,则情况比较棘手,您可以看到访问内的遍历TreeBin总是在synchronized块中完成.
| 归档时间: |
|
| 查看次数: |
741 次 |
| 最近记录: |