AtomicInteger 源码分析阅读

阅读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相关的操作实现,这里需要提一下的是Unsafe是不符合JAVA标准的,官方不推荐大家在编写自己的中使用它,因为它引入了和C++中指针相似的东西,但可以借用java.util.concurrent.atomic包下的类来使用。
2.valueOffset的值是变量value的内存首地址的偏移量。,它在AtomicInteger被加载时就被赋值了。
3.value其实就是存放实际值的变量,它被volatile 关键字修饰,说明对于其他线程是可见的。

可能大家还是不大能够了解valueOffset到底是个什么东西,有什么用,当时我也在这里卡了很久,接下来我来讲一下自己的分析过程。首先从字面意思来讲,应该是和value有关的一个变量。再看它是由objectFieldOffset()这个方法的返回值进行赋值的。我们查看一下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()方法的定义与声明


addGet()

这个测试中,我实例化了两个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 的含义。


valueOffset 的含义

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


compareAndSet

unsafe中的一个方法声明
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容

  • 在对J.U.C包的源码分析之前,首先介绍下一个比较重要的概念-CAS(Compare-and-Swap)。在J.U...
    泰迪的bagwell阅读 7,871评论 0 20
  • Java8张图 11、字符串不变性 12、equals()方法、hashCode()方法的区别 13、...
    Miley_MOJIE阅读 3,690评论 0 11
  • 独自去一个陌生的城市,没出发之前,和任何人说自己一个人去,你好厉害,注意安全,找同伴......如果第一次独自出去...
    噗梅阅读 185评论 0 0
  • 今日三朵玫瑰 1.早起 2.观看穿刺视频 3.准备明天考试 【幸福实修99天目标】 1.臣服父母,每天做打卡。 2...
    叶青丁当妈阅读 385评论 1 1
  • 那是个夏末秋初的中午,与朋友在路旁等车。 或许是“夏”感觉到季节即将终结,居然越发燥热,或许是“夏”想在最后关头发...
    孤独一刀阅读 304评论 0 5