本文主要是介绍并发读源码——AtomicInteger/AtomicLong/AtomicStampedReference,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 1. AtomicInteger描述
- 2. 源码解析
- 3. AtomicInteger演示示例
- 4. 多线程用法
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 updatesprivate 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减1public 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
这篇关于并发读源码——AtomicInteger/AtomicLong/AtomicStampedReference的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!