ConcurrentHashMap中tabAt方法分析

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);
}

该方法的作用是寻找指定数组在内存中i位置的数据

下面分析下原理。

首先解释下每个参数的含义。

U:Unsafe,它的作用是提供Java直接操作内存的方法
i:索引
ASHIFT:
ABASE:起始位置

下面是涉及到的3个方法

// 获取obj对象中offset偏移地址对应的object型field的值,支持volatile load语义。
public native Object getObjectVolatile(Object obj, long offset);

//获取数组中第一个元素的偏移量(get offset of a first element in the array)
public native int arrayBaseOffset(java.lang.Class aClass);

//获取数组中一个元素的大小(get size of an element in the array)
public native int arrayIndexScale(java.lang.Class aClass);

贴出关键性代码

Class<?> ak = Node[].class;
// 获取数组的起始位置
ABASE = U.arrayBaseOffset(ak);
// 获取数组的数据的大小,比如byte类型的数据为1,int类型的为4,long为8
int scale = U.arrayIndexScale(ak);
if ((scale & (scale - 1)) != 0)
    throw new Error("data type scale not a power of two");
// Integer.numberOfLeadingZeros(scale) 获得指定数字前面的0的个数
ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);

现在要提出一个问题,数组是如何是实现随机访问的?

通过寻址地址。

寻址地址的计算公式:

a[i]_address = base_address + i * data_type_size

base_address :起始地址

i:索引

data_type_size :数据大小,根据数据类型byte,boolean长度为1,char,short长度为2,float,int长度为3,long,double长度为4

我们可以用int数组来分析上面的关键代码

Class ak = int[].class;
// 起始位置:16,
// TODO 不明白为什么是16,所有的基本类型,还有Object,String,都是16,不清楚
// 如果有清楚的,麻烦回复到评论
int ABASE = unsafe.arrayBaseOffset(ak);
System.out.println("a=" + ABASE);
// 数据长度:4,int的长度为4
int scale = unsafe.arrayIndexScale(ak);
long ASHIFT;
// 2 = 31 - 29(4转化为二进制为100,由于是32位的,所以前面有29位0补位)
ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
System.out.println("ASHIFT=" + ASHIFT);

结合tabAt方法,i << 2 + ABASE 等价于 i * 4 + ABASE符合寻址地址公式。

所以tabAt的作用就是寻找指定数组在内存中i位置的数据。

参考:
[1]: https://blog.csdn.net/fenglibing/article/details/17119959
[2]: https://www.cnblogs.com/mickole/articles/3757278.html

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值