阅读java version "1.8.0_91"的ConcurrentHashMap源码发现put,get中分段锁不见了
public V put(K key, V value) { return putVal(key, value, false); } //该处说明了ifAbsent也调用该方法 final V putVal(K key, V value, boolean onlyIfAbsent) { if (key == null || value == null) throw new NullPointerException(); int hash = spread(key.hashCode()); int binCount = 0; for (Node<K,V>[] tab = table;;) { Node<K,V> f; int n, i, fh; if (tab == null || (n = tab.length) == 0) tab = initTable(); else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) { //CAS的方法添加新值 tab这个class偏移量为i的地方,添加一个新的node,无锁无压力 if (casTabAt(tab, i, null, new Node<K,V>(hash, key, value, null))) break; // no lock when adding to empty bin } else if ((fh = f.hash) == MOVED) tab = helpTransfer(tab, f); else { V oldVal = null; synchronized (f) { if (tabAt(tab, i) == f) { if (fh >= 0) { binCount = 1; for (Node<K,V> e = f;; ++binCount) { K ek; if (e.hash == hash && ((ek = e.key) == key || (ek != null && key.equals(ek)))) { oldVal = e.val; //如果是Absent 仅仅只是影响了该处2句代码 if (!onlyIfAbsent) e.val = value; break; } Node<K,V> pred = e; if ((e = e.next) == null) { pred.next = new Node<K,V>(hash, key, value, null); break; } } } else if (f instanceof TreeBin) { Node<K,V> p; binCount = 2; if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key, value)) != null) { oldVal = p.val; if (!onlyIfAbsent) p.val = value; } } } } if (binCount != 0) { if (binCount >= TREEIFY_THRESHOLD) treeifyBin(tab, i); if (oldVal != null) return oldVal; break; } } } addCount(1L, binCount); return null; } //为了搞明白段锁是否消失了所以查看了 private final Node<K,V>[] initTable() { Node<K,V>[] tab; int sc; while ((tab = table) == null || tab.length == 0) { if ((sc = sizeCtl) < 0) Thread.yield(); // lost initialization race; just spin else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) { try { if ((tab = table) == null || tab.length == 0) { int n = (sc > 0) ? sc : DEFAULT_CAPACITY; @SuppressWarnings("unchecked") Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n]; table = tab = nt; sc = n - (n >>> 2); } } finally { sizeCtl = sc; } break; } } return tab; }
/** * cas 的用法,如何更新数据 */ import java.lang.reflect.Field; import sun.misc.Unsafe; public class UnsafeTest { private static Unsafe unsafe; static { try { //通过反射获取rt.jar下的Unsafe类 Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); unsafe = (Unsafe) field.get(null); } catch (Exception e) { System.out.println("Get Unsafe instance occur error"+ e); } } public static void main(String[] args) throws Exception { Class clazz = Target.class; Field[] fields = clazz.getDeclaredFields(); for (Field f : fields) { // 获取属性偏移量,可以通过这个偏移量给属性设置 System.out.println(f.getName() + ":" + unsafe.objectFieldOffset(f)); } Target target = new Target(); Field intFiled = clazz.getDeclaredField("i") ; int a=(Integer)intFiled.get(target ) ; System.out.println("原始值是:"+a); System.out.println(unsafe.compareAndSwapInt(target, 12, 3, 0)); int b=(Integer)intFiled.get(target) ; System.out.println("改变之后的值是:"+b); } } class Target { int i=3; }
相关推荐
NULL 博文链接:https://107192468a.iteye.com/blog/2296911
主要介绍了java ConcurrentHashMap锁分段技术详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
ConcurrentHashMap使用了分段锁(Segment)来实现并发的读写操作,每个Segment都相当于一个小的HashMap,将整个哈希表分成多个部分。这样可以同时进行多个线程的并发读写操作,不会阻塞其他线程的访问。 需要注意的...
高薪程序员面试题精讲系列49之说说ConcurrentHashMap#put方法的源码及数。。。.pdf,这是一份不错的文件
本文将结合Java内存模型,分析JDK源代码,探索ConcurrentHashMap高并发的具体实现机制,包括其在JDK中的定义和结构、并发存取、重哈希和跨段操作,并着重剖析了ConcurrentHashMap读操作不需要加锁和分段锁机制的内在...
java源码剖析-ConcurrentHashMap
Java-concurrent-collections-concurrenthashmap-blockingqueue.pdf
Java——并发容器之ConcurrentHashMap;Java——并发容器之ConcurrentHashMap;Java——并发容器之ConcurrentHashMap;Java——并发容器之ConcurrentHashMap;Java——并发容器之ConcurrentHashMap;Java——并发...
ConcurrentHashMap可以做到读取数据不加锁,并且其内部的结构可以让其在进行写操作的时候能够将锁的粒度保持地尽量地小,允许多个修改操作并发进行,其关键在于使用了锁分离技术。它使用了多个锁来控制对hash表的...
ConcurrentHashMap之实现细节
Java并发编程之ConcurrentHashMap Java并发编程之ConcurrentHashMap.pdf
ConcurrentHashMap源码剖析
这时候ConcurrentHashMap达到容量扩容而忽略了ReservationNode情况,调用put的时候在synchronized(f)没有对ReservationNode处理,所以会出现死循环。 在jdk1.8和1.9中对比 http://gee.cs.oswego.edu/cgi- bin/...
Java利用ConcurrentHashMap实现本地缓存demo; 基本功能有缓存有效期、缓存最大数、缓存存入记录、清理线程、过期算法删除缓存、LRU算法删除、获取缓存值等功能。 复制到本地项目的时候,记得改包路径哦~
源码分析见我博文:http://blog.csdn.net/wabiaozia/article/details/50684556
java7-8中的 HashMap和ConcurrentHashMap全解析
线程是系统中可执行调度的最小单位。线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,规避资源耗尽...集合的详细描述,以及集合中的异同点,HashMap不同jdk版本区别,ConcurrentHashMap介绍。
下面小编就为大家带来一篇基于Java并发容器ConcurrentHashMap#put方法解析。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
1.面向对象的的特征有哪些方面 2.论述类的加载机制 3.对于反射的理解 4.GC是什么?为什么要有GC ...23.ConcurrentHashMap分段式加锁是如何实现 24.HashMap存储null值的底层实现 25.叙述线程的生命周期