AtomicInteger 源码分析阅读

本文记录了作者阅读Java 1.8线程池源码时对AtomicInteger类的研究。AtomicInteger可原子性操作Integer对象,使用CAS无锁算法。作者分析了其关键属性,如unsafe负责CAS操作、valueOffset是value内存首地址偏移量、value存放实际值。还通过测试明确了valueOffset含义及CAS算法底层依赖。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


阅读java源码可能是每一个java程序员的必修课,只有知其所以然,才能更好的使用java,写出更优美的程序,阅读java源码也为我们后面阅读java框架的源码打下了基础。阅读源代码其实就像再看一篇长篇推理小说一样,不能急于求成,需要慢慢品味才行。这一系列的文章,记录了我阅读源码的收获与思路,读者也可以借鉴一下,也仅仅是借鉴,问渠那得清如许,绝知此事要躬行!要想真正的成为大神,还是需要自己亲身去阅读源码而不是看几篇分析源码的博客就可以的。

正文

最近在看JAVA1.8线程池源码的时候,发现对于AtomicInteger类的使用不太熟悉,所以就专门研究了一下,有一些收获。AtomicInteger是juc(java.util.concurrent)包下提供的一个可以原子性操作Integer对象的类。通过它,我们可以很方便的对Integer进行线程安全的加、减、改值等操作。其原理是使用的CAS无锁算法。

private static final long serialVersionUID = 6214790243416807050L;

// setup to use Unsafe.compareAndSwapInt for updates

//JAVA实现CAS算法的类,整个类有关线程安全的操作,都是借助它来实现。

private static final Unsafe unsafe = Unsafe.getUnsafe();

//变量value的内存首地址的偏移量。

private static final long valueOffset;

//静态代码块,在类加载时运行

static {

try {

valueOffset = unsafe.objectFieldOffset

(AtomicInteger.class.getDeclaredField(value));

} catch (Exception ex) { throw new Error(ex); }

}

//存放int值

private volatile int value;

1.unsafe 其实就是负责与CAS相关的操作实现。
2.valueOffset的值是变量value的内存首地址的偏移量。,它在AtomicInteger被加载时就被赋值了。
3.value其实就是存放实际值的变量,它被volatile 关键字修饰,说明对于其他线程是可见的。
可能大家还是不大能够了解valueOffset到底是个什么东西,有什么用,当时我也在这里卡了很久,接下来我来讲一下自己的分析过程。首先从字面意思来讲,应该是和value有关的一个变量。再看它是由objectFieldOffset()这个方法的返回值进行赋值的。我们查看一下objectFieldOffset()的声明定义:
发现并没有任何描述,但是通过百度发现说是value在内存中首地址。出于严禁的角度,我就写了一个测试来看看:

public class Main {

public static void main(String[] args) {

AtomicInteger a=new AtomicInteger(1);

AtomicInteger b=new AtomicInteger(1);

int c=a.addAndGet(5);

b.addAndGet(4);

System.out.println(a.get());

System.out.println(c);

}

}

addAndGet()方法的定义与声明

这个测试中,我实例化了两个AtomicInteger 对象:a和b,同时在调用的方法addAndGet()中打了断点。
最后debug发现,两个变量的valueOffset值都为12。说明valueOffset就是value内存首地址的偏移量。到这里或许大家还想问,这个偏移应该是针对于什么的偏移呢?你偏移量总得有个参照位置吧。这里就要回到我们valueOffset的定义与赋值了。

private static final long valueOffset;

//静态代码块,在类加载时运行

static {

try {

valueOffset = unsafe.objectFieldOffset

(AtomicInteger.class.getDeclaredField(value));

} catch (Exception ex) { throw new Error(ex); }

}

我们可以看到,valueOffset 是一个静态常量,并且在类加载时就被赋值了。那么这个类在编译后的字节码是一定的,但是存放对象的首地址是随机的,所以这里的偏移应该是相对于对象实例的首地址。如果大家看不明白,请看下面这幅图,这幅图简介明了的描述了valueOffset 的含义。

再联系到AtomicInteger在调用unsafe接口时,都将this和valueOffset 作为传入参数(如下图),我们可以了解到unsafe实现的CAS算法是依赖底层实现的(因为方法声明有native关键字),我们为其提供具体的内存地址,即this+valueOffset ,就可以让其找到要进行原子性操作的变量value,并进行修改。




转载于:https://juejin.im/post/5b88e4efe51d4538e331b7f5

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值