neo 的小窝
欢迎来到 neo 的小窝,更多参见我的 GitHub账号 http://github.com/neocxf

  ConcurrentHashMap 中为了提高并发时锁的效率,对底层做了很多优化,其中一点就是对存储数据的数组的操作的优化,在Java 8中使用了 CAS 对要操作的数组进行操作

Unsafe 的获取

Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
Unsafe unsafe = (Unsafe) f.get(null);

存储数据数组的获取

  在高并发环境下,直接以index的形式对数据的元素进行各种操作是不安全的,而直接对元素数组进行加锁,控制读取,则效率低,吞吐量下降。就像拆分解决问题的概念一样,ConcurrentHashMap 采用 lock-free的形式具体操作每个元素。为了实现这种粒度,需要使用 Unsafe 工具集中的一下几个方法

// 数组对象的起始 offset
long ABASE = unsafe.arrayBaseOffset(Class)
// 对象的每个元素的长度,(boolean 1, char 2, short 2, int 4, reference 4, float 4, double 8, long 8) int scale = unsafe.arrayIndexScale(Class)
// 需要移动的位数,如果数组元素是 int类型,则ASHIFT 为 2,即元素的偏移量为 ABASE + (1 << ASHIFT) * i. 第一个元素为 ABASE + 4; 第二个元素的偏移量为 ABASE + 8
int ASHIFT = 31 - Integer.numberOfLeadingZeros()

// 使用 unsafe 以原子化的形式读取数组的第 i 个元素
static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {
return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);
}

 数组元素的插入

static final <K,V> void setTabAt(Node<K,V>[] tab, int i, Node<K,V> v) {
        U.putObjectVolatile(tab, ((long)i << ASHIFT) + ABASE, v);
    }

数组元素的更新

static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i,
                                        Node<K,V> c, Node<K,V> v) {
        return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
    }

 

posted on 2020-03-23 10:40  neo的小窝  阅读(763)  评论(0)    收藏  举报