Java中GetAndAdd函数

GetAndAdd

解释:以原子方式将给定值与当前值相加;

源码:

 public final int getAndAdd(int delta) {

     return unsafe.getAndAddIn(this,valueOffset,delta);

 }

补充(原子更新基本类型):

  • AtomicBoolean:原子更新布尔变量;

  • AtomicInteger:原子更新整型变量;

  • AtomicLong:原子更新长整型变量;

这里以AtomicInteger为例进行说明,AtomicInteger提供的部分方法如下:

 public class AtomicInteger extends Number implements java.io.Serializable {
     //返回当前的值
     public final int get() {
         return value;
     }
     //原子更新为新值并返回旧值
     public final int getAndSet(int newValue) {
         return unsafe.getAndSetInt(this, valueOffset, newValue);
     }
     //最终会设置成新值
     public final void lazySet(int newValue) {
         unsafe.putOrderedInt(this, valueOffset, newValue);
     }
     //如果输入的值等于预期值,则以原子方式更新为新值
     public final boolean compareAndSet(int expect, int update) {
         return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
     }
     //原子自增
     public final int getAndIncrement() {
         return unsafe.getAndAddInt(this, valueOffset, 1);
     }
     //原子方式将当前值与输入值相加并返回结果
     public final int getAndAdd(int delta) {
         return unsafe.getAndAddInt(this, valueOffset, delta);
     }
 }

为了说明AtomicInteger的原子性,这里代码演示多线程对一个int值进行自增操作,最后输出结果,代码如下:

package com.rhwayfun.concurrency.r0405;

import java.util.concurrent.atomic.AtomicInteger;

/**
* Created by rhwayfun on 16-4-5.
*/
public class AtomicIntegerDemo {

    private static AtomicInteger atomicInteger = new AtomicInteger(0);

    public static void main(String[] args){
        for (int i = 0; i < 5; i++){
            new Thread(new Runnable() {
                public void run() {
                    //调用AtomicInteger的getAndIncement返回的是增加之前的值
                     System.out.println(atomicInteger.getAndIncrement());
                }
            }).start();
        }
        System.out.println(atomicInteger.get());
    }
}

输出结果如下:

    0
    1
    2
    3
    4
    5
    5

可以看到在多线程的情况下,得到的结果是正确的,但是如果仅仅使用int类型的成员变量则可能得到不同的结果。这里的关键在于getAndIncrement是原子操作,那么是如何保证的呢?

getAndIncrement方法的源码如下:

public final int getAndIncrement() {
    return unsafe.getAndAddInt(this, valueOffset, 1);
}

public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
        var5 = this.getIntVolatile(var1, var2);
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

    return var5;
}

public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

到这里可以发现最终调用了native方法来保证更新的原子性。


参考博客:
http://http://blog.csdn.net/u011116672/article/details/51068828

8/16/2017 10:57:06 PM

你可能感兴趣的:(java学习)