欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java nio AtomicInteger源码分析

程序员文章站 2022-06-19 15:05:38
目录简介字段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...

目录

简介

字段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 

java nio AtomicInteger源码分析

java nio AtomicInteger源码分析

java nio AtomicInteger源码分析

字段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

相关标签: java多线程