目录

简介

字段unsafe,valueOffset,value,2个构造函数

方法get,set,lazySet,getAndSet,compareAndSet,weakCompareAndSet

方法5个getAndXXX,5个XXXAndGet

方法toString,4个XXXValue

简介

package java.util.concurrent.atomic;
import java.util.function.IntUnaryOperator;
import java.util.function.IntBinaryOperator;
import sun.misc.Unsafe;

/**
 * 一个可以自动更新的int值。看java.util.concurrent.atomic包描述原子变量属性的规范。
 * AtomicInteger用于像原子递增计数器这样的应用程序,不能用作java.lang.Integer的替代品。
 * 然而,这个类确实扩展了Number,允许处理基于数字的类的工具和实用程序进行统一访问。
 *
 * @since 1.5
 * @author Doug Lea
*/
public class AtomicInteger extends Number implements java.io.Serializable 

字段unsafe,valueOffset,value,2个构造函数

    private static final long serialVersionUID = 6214790243416807050L;

    // Unsafe构造器私有,且是一个单例模式,只能通过单例方法getUnsafe获得实例。可以使用指针偏移操作。
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    // value的偏移量,用于unsafe对这个对象的对应的偏移量进行操作
    private static final long valueOffset;

    static {
        try {
        	// 在静态初始化块中,通过反射的Field和Unsafe的objectFieldOffset,获得了value这个域相对于AtomicInteger对象的地址偏移量。
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }

    // value域,是AtomicInteger对象的数据来源。
    // 它被设置为volatile的,使得对value的操作结果都具有可见性。
    //(注意,不保证原子性,比如value++这样的复合操作)
    private volatile int value;

    /**
     * 使用给定的初始值创建一个新的AtomicInteger。
     *
     * @param initialValue the initial value
     */
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }

    /**
     * 使用初始值0创建一个新的AtomicInteger。
     */
    public AtomicInteger() {
    }

方法get,set,lazySet,getAndSet,compareAndSet,weakCompareAndSet


    /**
     * 获取当前值。
     * 可见get/set没有加锁,但在多线程环境下,这两个函数也能保证线程安全。
     * 因为return操作和赋值操作都是原子操作,所以两个函数都有原子性了,且volatile的value又使得对value的操作结果都具有可见性。
     *
     * @return the current value
     */
    public final int get() {
        return value;
    }

    /**
     * 设置为给定值。
     *
     * @param newValue the new value
     */
    public final void set(int newValue) {
        value = newValue;
    }

    /**
     * 最终设置为给定的值。
     * 简单地说,lazySet使得程序执行变快了,但损失了可见性,
     * 可见性直到有某个volatile write操作或同步操作才能恢复。
     * volatile write操作会在该操作前添加 store-store内存屏障,在该操作之后添加 store-load内存屏障,但lazySet却省去了这个 store-load内存屏障。
     * 这样,lazySet操作不会与任何先前的写操作重新排序,但可以与后续操作重新排序
     * (lazySet操作因为重排序,可能排在了 它的后续操作的后面,自然也就不能保证其他线程可见了)。
     *
     * @param newValue the new value
     * @since 1.6
     */
    public final void lazySet(int newValue) {
        unsafe.putOrderedInt(this, valueOffset, newValue);
    }

    /**
     * 原子地设置给定值并返回旧值。
     * 
     *     	public final int getAndSetInt(Object o, long offset, int newValue) {
     *		      int v;
     *		      do {
     *		          v = getIntVolatile(o, offset);
     *		       } while (!compareAndSwapInt(o, offset, v, newValue));
     *		       return v;
     *		  }
     * 上来就直接调用了Unsafe的操作。Unsafe的getAndSetInt逻辑,利用了 循环和CAS操作(compareAndSwap)和volatile变量,
     * 使得更新操作不需要加锁就能完全,不过缺点是有可能会循环若干次才能成功。
     * getIntVolatile使得线程总是获得变量的最新更新的值。
     * 
     * compareAndSwapInt的前两个参数,根据指针o和指针偏移offset和int值所占字节数量4,可以读取出该对象中的value值是多少。
     * 如果通过指针偏移发现 对象的value值 和 expected相同,那么将 对象的value值 设为 x,并返回true;
     * 如果通过指针偏移发现 对象的value值 和 expected不相同,直接返回false。
     * 
     * 而循环配合compareAndSwapInt,则使得,只有当对象的value值 在v = getIntVolatile(o, offset)和
     * compareAndSwapInt(o, offset, v, newValue)的执行过程之间没有被其他线程修改的情况下
     * (有可能执行前者之后,线程就被切换出去了,然后线程重新开始执行时,值已经被修改了),才会设置新值成功。
     * 这个函数的缺点在于,有可能需要执行好多次循环,函数才能结束。
     *		    
     *
     * @param newValue the new value
     * @return the previous value
     */
    public final int getAndSet(int newValue) {
        return unsafe.getAndSetInt(this, valueOffset, newValue);
    }

    /**
     * 如果当前值==期望值,则自动将值设置为给定的更新值。
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful. False return indicates that
     * the actual value was not equal to the expected value.
     */
    public final boolean compareAndSet(int expect, int update) {
    	// compareAndSet函数相比上一个函数,没有循环了,粒度变小了。它只是让你执行一次CAS操作,结果成功或者失败。
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

    /**
     * 如果当前值==期望值,则自动将值设置为给定的更新值。
     *
     * <p>可能会错误地失败,并且不提供排序保证,所以它很少是compareAndSet的合适的替代品。
     * 
     * compareAndSet函数的weak版,但实现和compareAndSet一模一样,只能说,源码作者还没来得及写它的不同实现呢。
     * 它可能会返回 虚假的失败,且不提供排序保证。
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful
     */
    public final boolean weakCompareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

方法5个getAndXXX,5个XXXAndGet


    /**
     * 将当前值原子地加1。
     * 
     * 这几个函数都调用unsafe.getAndAddInt。
     * 
     *     public final int getAndAddInt(Object o, long offset, int delta) {
     *         int v;
     *         do {
     *             v = getIntVolatile(o, offset);
     *         } while (!compareAndSwapInt(o, offset, v, v + delta));
     *         return v;
     *     }
     *  方法和getAndSetInt差不多,区别再去新的值不在固定,而是v+delta   
     * 
     * 区别在于:
     * getAndIncrement相当于i++,getAndAddInt刚好返回旧值。
     * getAndDecrement相当于i--。
     * getAndAdd相当于i += n,但是它却返回旧值。
     * 
     * incrementAndGet相当于++i,返回 getAndAddInt的旧值再加1.
     * decrementAndGet相当于--i,返回 getAndAddInt的旧值再减1.
     * addAndGet相当于i += n,返回 getAndAddInt的旧值再加n。
     *
     * @return the previous value
     */
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }

    /**
     * 使当前值原子地递减一。
     *
     * @return the previous value
     */
    public final int getAndDecrement() {
        return unsafe.getAndAddInt(this, valueOffset, -1);
    }

    /**
     * 原子地将给定值添加到当前值。
     *
     * @param delta the value to add
     * @return the previous value
     */
    public final int getAndAdd(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta);
    }

    /**
     * 将当前值原子地加1。
     *
     * @return the updated value
     */
    public final int incrementAndGet() {
    	// 先得到原来的值,然后直接进行加减,然后返回
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }

    /**
     * Atomically decrements by one the current value.
     *
     * @return the updated value
     */
    public final int decrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
    }

    /**
     * Atomically adds the given value to the current value.
     *
     * @param delta the value to add
     * @return the updated value
     */
    public final int addAndGet(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
    }

    /**
     * 用应用给定函数的结果自动更新当前值,返回前一个值。
     * 这个函数应该是没有副作用的,因为当尝试的更新由于线程间的争用而失败时,它可能会被重新应用。
     * 
     * IntUnaryOperator是个函数式接口,看名字Unary就知道,它代表一个int的一元方程。
     * 如果当你需要根据旧值来更新新值,且需要将更新的逻辑包含在函数式接口中时,就需要使用该函数。
     * 注意,传入的IntUnaryOperator不应该有副作用,它应该只操作自己的局部变量。
     * updateAndGet与前者的区别在于,它返回新值。
     *
     * @param updateFunction a side-effect-free function
     * @return the previous value
     * @since 1.8
     */
    public final int getAndUpdate(IntUnaryOperator updateFunction) {
        int prev, next;
        do {
        	// 先得到当前的值,然后用updateFunction计算结果
        	//然后判断当前值是否是prev,是的话,设置为next
            prev = get();
            next = updateFunction.applyAsInt(prev);
        } while (!compareAndSet(prev, next));
        return prev;
    }

    /**
     * Atomically updates the current value with the results of
     * applying the given function, returning the updated value. The
     * function should be side-effect-free, since it may be re-applied
     * when attempted updates fail due to contention among threads.
     *
     * @param updateFunction a side-effect-free function
     * @return the updated value
     * @since 1.8
     */
    public final int updateAndGet(IntUnaryOperator updateFunction) {
        int prev, next;
        do {
            prev = get();
            next = updateFunction.applyAsInt(prev);
        } while (!compareAndSet(prev, next));
        return next;
    }

    /**
     * 将给定函数应用到当前值和给定值的结果自动更新当前值,并返回前一个值。
     * 这个函数应该是无效果的,因为当由于线程间的争用而导致竞争更新失败时,它可能会被重新应用。
     * 函数的第一个参数是当前值,第二个参数是给定的update。
     * 
     * IntBinaryOperator是int的二元方程,所以还需要一个参数x。
     *
     * @param x the update value
     * @param accumulatorFunction a side-effect-free function of two arguments
     * @return the previous value
     * @since 1.8
     */
    public final int getAndAccumulate(int x,
                                      IntBinaryOperator accumulatorFunction) {
        int prev, next;
        do {
            prev = get();
            next = accumulatorFunction.applyAsInt(prev, x);
        } while (!compareAndSet(prev, next));
        return prev;
    }

    /**
     * Atomically updates the current value with the results of
     * applying the given function to the current and given values,
     * returning the updated value. The function should be
     * side-effect-free, since it may be re-applied when attempted
     * updates fail due to contention among threads.  The function
     * is applied with the current value as its first argument,
     * and the given update as the second argument.
     *
     * @param x the update value
     * @param accumulatorFunction a side-effect-free function of two arguments
     * @return the updated value
     * @since 1.8
     */
    public final int accumulateAndGet(int x,
                                      IntBinaryOperator accumulatorFunction) {
        int prev, next;
        do {
            prev = get();
            next = accumulatorFunction.applyAsInt(prev, x);
        } while (!compareAndSet(prev, next));
        return next;
    }

方法toString,4个XXXValue


    /**
     * 返回当前值的字符串表示形式。
     * 
     * @return the String representation of the current value
     */
    public String toString() {
        return Integer.toString(get());
    }

    /**
     * 返回这个AtomicInteger的int值。
     */
    public int intValue() {
        return get();
    }

    /**
     * 返回该AtomicInteger的值作为扩展原语转换后的long值。
     * 
     * @jls 5.1.2 Widening Primitive Conversions
     */
    public long longValue() {
        return (long)get();
    }

    /**
     * Returns the value of this {@code AtomicInteger} as a {@code float}
     * after a widening primitive conversion.
     * @jls 5.1.2 Widening Primitive Conversions
     */
    public float floatValue() {
        return (float)get();
    }

    /**
     * Returns the value of this {@code AtomicInteger} as a {@code double}
     * after a widening primitive conversion.
     * @jls 5.1.2 Widening Primitive Conversions
     */
    public double doubleValue() {
        return (double)get();
    }

本文地址:https://blog.csdn.net/xushiyu1996818/article/details/113936345