并发读源码——AtomicInteger/AtomicLong/AtomicStampedReference

1. AtomicInteger描述

AtomicInteger从名字上看是操作Integer整数的,但Integer是线程不安全的,AtomicInteger是线程安全的。AtomicInteger的作用可以把两个Integer对象的加减乘除等操作变成一个原子操作,如果对Integer的操作不用AtomicInteger,也可以选择用synchronized锁住两个Integer对象的操作,synchronized是重量级锁,悲观锁,资源开销大,而AtomicInteger中的操作方法采用的轻量级锁,乐观锁,下面会进行分析。

2. 源码解析

AtomicInteger的原理就是运用了乐观锁
悲观锁与乐观锁区别:

  • 悲观锁:在并发操作之前认为冲突概率比较大,读操作之前就上锁。比如synchronized关键字
  • 乐观锁:在并发操作之前认为冲突的概率比较小,读操作不上锁,等到写操作时,再判断数据在此期间是否被修改了,如果数据被修改了,则就把数据重新读出来,重新执行该过程;如果原始数据没被修改,就直接把新值写回去。

AtomicInteger的乐观锁是通过Unsafe下的compareAndSwapInt方法执行的,AtomicInteger是通过乐观锁中的自旋锁方式获取锁的(自旋锁:不放弃CPU,空转,不停的重试,典型的就是通过for进行循环)。

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

/**
 * An {@code int} value that may be updated atomically.  See the
 * {@link java.util.concurrent.atomic} package specification for
 * description of the properties of atomic variables. An
 * {@code AtomicInteger} is used in applications such as atomically
 * incremented counters, and cannot be used as a replacement for an
 * {@link java.lang.Integer}. However, this class does extend
 * {@code Number} to allow uniform access by tools and utilities that
 * deal with numerically-based classes.
 *
 * @since 1.5
 * @author Doug Lea
*/
public class AtomicInteger extends Number implements java.io.Serializable {
    private static final long serialVersionUID = 6214790243416807050L;

    // setup to use Unsafe.compareAndSwapInt for updates
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    /*valueOffset是下面定义的value在AtomicInteger类内存的偏移量,通过这个偏移量可以定位value的值,下面读写AtomicInteger 对象中的值都是valueOffset进行操作的
	*/
    private static final long valueOffset;

	/*因为value是private类型的,是不能直接获取的,因此通过反射形式获取value变量,然后通过java的native方法unsafe.objectFieldOffset获取value相对AtomicInteger类的内存偏移量*/
    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }

    private volatile int value;

    /*初始化时指定value的值*/
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }

    /*默认初始化方式,value值默认为0,因为value是int类型的*/
    public AtomicInteger() {
    }

   /*获取value值*/
    public final int get() {
        return value;
    }

    /*修改value值,因为value是volatile类型的,会立即把value中的值刷入主内存,其它线程可以看到修改*/
    public final void set(int newValue) {
        value = newValue;
    }

    /*lazySet方法现实中很少用,不会立即把value刷入主内存,但最终会刷值,保证最终一致性*/
    public final void lazySet(int newValue) {
        unsafe.putOrderedInt(this, valueOffset, newValue);
    }

    /*先获取value的值,然后修改value值为新值newValue,整个动作是原子性的,通过unsafe.getAndSetInt方式实现*/
    public final int getAndSet(int newValue) {
        return unsafe.getAndSetInt(this, valueOffset, newValue);
    }

    /*封装了Unsafe中compareAndSwapInt的native函数,compareAndSet有两个参数,expect指变量的旧值,是读出来的值,写回去的时候希望没有没其他线程修改,所以是expect;第二个参数是update,值变量的新值,修改过的,希望写入的value值。当expect等于变量当前值时,说明在修改期间没有其他线程对此变量进行修改,所以可以成功写入,变量更新为update,返回true,否则返回false*/
    /*compareAndSwapInt有4个参数,第一个参数是AtomictInteger对象,第二个是成员变量value相对AtomictInteger类的内存偏移量,expect和update保持不变*/
   /**
     * 如果内存中的value成员变量值等于expect的值,就把update值更新到value中,compareAndSwapInt方法是原子的,先比较,如果相等就直接更新(根据value在AtomicInteger中内存偏移量valueOffset来更新)
     */
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

    /**
     * weakCompareAndSet方法与compareAndSet类似,但weakCompareAndSet不会插入内存屏障,不能保障volatile的原子性
     */
    public final boolean weakCompareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

    /**
     * 先获取value成员变量的值,然后对value增加1
     */
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }

    /**
     * 先获取value成员变量的值,然后对value减1
    public final int getAndDecrement() {
        return unsafe.getAndAddInt(this, valueOffset, -1);
    }

    /**
     * 先获取value成员变量的值,然后把delta加到value上
     */
    public final int getAndAdd(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta);
    }

    /**
     * 先对成员变量value增加1,然后把修改后的值更新到value中
     */
    public final int incrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }

    /**
     * 先对成员变量value减1,然后把修改后的值更新到value中
     */
    public final int decrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
    }

    /**
     * 先对成员变量value增加delta,然后把修改后的值更新到value中
     */
    public final int addAndGet(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
    }

    /**
     * 先获取value的值赋值给prev,然后对prev执行功能函数updateFunction,把结果next更新到value中
     */
     /*该方法用到了自旋锁,当prev的值等于内存中的value值时,才会把next的值更新到value中,否则该方法会进行自旋,即一遍遍的获取锁重试,当prev的值等于内存中的value值时进行更新*/
    public final int getAndUpdate(IntUnaryOperator updateFunction) {
        int prev, next;
        do {
            prev = get();
            next = updateFunction.applyAsInt(prev);
        } while (!compareAndSet(prev, next));
        return prev;
    }

    /**
     * 该方法与上面方法原理相同,只是先更新后,再获取value值
     */
    public final int updateAndGet(IntUnaryOperator updateFunction) {
        int prev, next;
        do {
            prev = get();
            next = updateFunction.applyAsInt(prev);
        } while (!compareAndSet(prev, next));
        return next;
    }

    /**
     * 该方法与上面方法原理相同,只是功能函数变为了IntBinaryOperator,执行两个整数返回一个整数;
     * 先获取value值,然后功能函数执行后的结果更新到value中
     */
    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;
    }

    /**
     * 该方法与上面函数类似,只是先更新value值,然后获取返回更新后的value值
     */
    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;
    }

    /**
     * 把value值转化为String 类型
     */
    public String toString() {
        return Integer.toString(get());
    }

    /**
     *获取value成员变量值
     */
    public int intValue() {
        return get();
    }

    /**
     * 把value值转化为long类型
     */
    public long longValue() {
        return (long)get();
    }

    /**
     * 把value值转化为float类型
     */
    public float floatValue() {
        return (float)get();
    }

    /**
     * 把value值转化为double类型
     */
    public double doubleValue() {
        return (double)get();
    }

}

3. AtomicInteger演示示例

package com.lzj.atomic;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.IntBinaryOperator;
import java.util.function.IntUnaryOperator;

public class AtomicIntegerDemo2 {

	public static void main(String[] args) {
		get();
		set();
		getAndSet();
		getAndIncrement();
		getAndDecrement();
		getAndAdd();
		incrementAndGet();
		decrementAndGet();
		addAndGet();
		getAndUpdate();
		updateAndGet();
		getAndAccumulate();
		accumulateAndGet();
	}
	
	/*测试AtomicInterger.get方法*/
	public static void get() {
		AtomicInteger at = new AtomicInteger(10);
		int value = at.get();
		System.out.println("get() : " + value);
	}
	
	/*测试AtomicInteger.get方法*/
	public static void set() {
		AtomicInteger at = new AtomicInteger(10);
		at.set(20);
		System.out.println("set()" + at.get());
	}
	
	/*测试AtomicInteger.getAndSet*/
	public static void getAndSet() {
		AtomicInteger at = new AtomicInteger(10);
		int oldValue = at.getAndSet(20);
		System.out.println("getAndSet : " + at.get());
		System.out.println("getAndSet : " + oldValue);
	}

	/*测试AtomicInteger.getAndIncrement*/
	public static void getAndIncrement() {
		AtomicInteger at = new AtomicInteger(10);
		at.getAndIncrement();
		System.out.println("getAndIncrement : " + at.get());
	}
	
	public static void getAndDecrement() {
		AtomicInteger at = new AtomicInteger(10);
		at.getAndDecrement();
		System.out.println("getAndDecrement : " + at.get());
	}
	
	/*测试AtomicInteger.getAndAdd*/
	public static void getAndAdd() {
		AtomicInteger at = new AtomicInteger(10);
		at.getAndAdd(5);
		System.out.println("getAndAdd : " + at.get());
	}
	
	/*测试AtomicInteger.incrementAndGet*/
	public static void incrementAndGet() {
		AtomicInteger at = new AtomicInteger(10);
		int current = at.incrementAndGet();
		System.out.println("incrementAndGet() : " + at.get());
		System.out.println("incrementAndGet() : " + current);
	}
	
	/*AtomicInteger.decrementAndGet*/
	public static void decrementAndGet() {
		AtomicInteger at = new AtomicInteger(10);
		int current = at.decrementAndGet();
		System.out.println("decrementAndGet() : " + at.get());
		System.out.println("decrementAndGet() : " + current);
	}
	
	/*测试AtomicInteger.addAndGet*/
	public static void addAndGet() {
		AtomicInteger at = new AtomicInteger(10);
		int current = at.addAndGet(10);
		System.out.println("addAndGet() : " + at.get());
		System.out.println("current : " + current);
	}
	
	/*测试AtomicInteger.getAndUpdate*/
	public static void getAndUpdate() {
		AtomicInteger at = new AtomicInteger(11);
		IntUnaryOperator updateFunction = x -> x/2;
		int old = at.getAndUpdate(updateFunction);
		System.out.println("getAndUpdate() : " + at.get());
		System.out.println("getAndUpdate() : " + old);
	}
	
	/*测试AtomicInteger.updateAndGet*/
	public static void updateAndGet() {
		AtomicInteger at = new AtomicInteger(11);
		IntUnaryOperator updateFunction = x -> x/2;
		int current = at.updateAndGet(updateFunction);
		System.out.println("updateAndGet() : " + at.get());
		System.out.println("updateAndGet() : " + current);
	}
	
	/*测试AtomicInteger。getAndAccumulate*/
	public static void getAndAccumulate() {
		AtomicInteger at = new AtomicInteger(11);
		IntBinaryOperator accumulatorFunction = (x,y) -> x / y;
		int old = at.getAndAccumulate(2, accumulatorFunction);
		System.out.println("getAndAccumulate() : " + at.get());
		System.out.println("getAndAccumulate() : " + old);
	}
	
	/*测试AtomicInteger.accumulateAndGet*/
	public static void accumulateAndGet() {
		AtomicInteger at = new AtomicInteger(11);
		IntBinaryOperator accumulatorFunction = (x,y) -> x / y;
		int current = at.accumulateAndGet(2, accumulatorFunction);
		System.out.println("accumulateAndGet() : " + at.get());
		System.out.println("accumulateAndGet() : " + current);
	}
}

执行结果如下

get() : 10
set()20
getAndSet : 20
getAndSet : 10
getAndIncrement : 11
getAndDecrement : 9
getAndAdd : 15
incrementAndGet() : 11
incrementAndGet() : 11
decrementAndGet() : 9
decrementAndGet() : 9
addAndGet() : 20
current : 20
getAndUpdate() : 5
getAndUpdate() : 11
updateAndGet() : 5
updateAndGet() : 5
getAndAccumulate() : 5
getAndAccumulate() : 11
accumulateAndGet() : 5
accumulateAndGet() : 5

4. 多线程用法

package com.lzj.atomic;

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicDemo1 {

	public static AtomicInteger count = new AtomicInteger(10);
	
	public void add() {
		count.getAndIncrement();
		System.out.println("thread1 : " + count);
	}
	
	public void dec() {
		System.out.println("thread2 : " + count);
		count.getAndDecrement();
	}
	
	public static void main(String[] args) {
		AtomicDemo1  atomicDemo1 = new AtomicDemo1();
		Runnable run1 = new Runnable() {
			public void run() {
				atomicDemo1.add();
				System.out.println("thread1 : " + atomicDemo1.count);
			}
		};
		
		Runnable run2 = new Runnable() {
			public void run() {
				atomicDemo1.dec();
				System.out.println("thread2 : " + atomicDemo1.count);
			}
		};
		
		Thread thread1 = new Thread(run1);
		Thread thread2 = new Thread(run2);
		thread1.start();
		
		thread2.start();
	}
}

另外,AtomicLong与AtomicInteger除了value的类型不一样,其它几乎都类似。
AtomicStampedReference与AtomicInteger源码基本类似,只是AtomicInteger用来处理整数类型,通过自旋锁的方式利用compareAndSwapInt来解决CAS问题;而AtomicStampedReference用来处理对象,通过自旋锁的方式利用compareAndSwapObject来解决CAS问题,关于AtomicStampedReference的详解参考AtomicStampedReference

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值