在java.util.concurrent.atomic包下面,有许多的原子类,这里面的操做类型大多数与JAVA中基本类型的包装类对应。目的是为了防止高并发的状况下,各个线程操做产生错误数据。这里就经过AtomicInteger这个类进行为你们简单讲解下。java
经过源码咱们发现。AtomicInteger中只有三个属性,一个
unsafe
对象属性,一个valueOffset
属性以及一个被volatile修饰的value
属性。多线程
1.unsafe
属性能够看到是由Unsafe类调用其静态方法生成。并发
public static Unsafe getUnsafe() {
Class var0 = Reflection.getCallerClass();
if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
throw new SecurityException("Unsafe");
} else {
return theUnsafe;
}
}
复制代码
Unsafe类提供了硬件级别的原子操做。里面有许多的本地方法。JDK中的一些无锁并发操做类都是基于它,里面最主要的就是CAS相关操做。这块我就不详细说明了(有兴趣的小伙伴能够去了解下)。app
2.valueOffset
属性是当前类中值value对应的内存起始地址。经过当前类中的静态代码块能够看出,他的赋值状况:函数
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
复制代码
他是经过unsafe获取到当前类中的属性的起始地址。来进行赋值。点击到下面能够看到调用的objectFieldOffset
的native方法进行调用获取。高并发
3.value
属性就是当前类中的值,这里也就是咱们所须要的值。这里能够从外部传递过来。性能
public AtomicInteger(int initialValue) {
value = initialValue;
}
复制代码
由当前的类型,咱们就能了解到这是一个原子类相关操做,即每个操做不须要考虑多线程并发的问题。里面的方法以下:this
刚开始的构造函数以及get和set方法在这里就不作说明了。atom
1.lazySet(int)
这个方法字面上说是懒设值,看到对应方法上面的注解说。这个会最终设值(仍是有点懵。。)。因而点击进去查看对应调用的方法:spa
public native void putOrderedInt(Object var1, long var2, int var4);
复制代码
看到里面调用的是unsafe的方法,putOrderedInt
方法是putIntVolatile
方法的延迟实现,不保证值的改变被其余线程当即看到。同时,unsafe里面还有对应的putVolatile
方法,改方法能将改动的值当即刷新到内存中。以及存在普通的putInt
方法,该方法不能保证当即刷新到内存中。
2.getAndSet(int newValue)
方法是为了设置值,里面就用到了value的内存地址进行设值。
public final int getAndSet(int newValue) {
return unsafe.getAndSetInt(this, valueOffset, newValue);
}
复制代码
3.compareAndSet(int expect, int update)
这个方法就是基于CAS实现的更新数值。 经过无无锁将多线程设置值的问题解决。若是设置成功返回true,反之没设置成功。同时这里也为其余操做提供了一个准确的保证。
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
复制代码
4.weakCompareAndSet(int expect, int update)
方法是针对于当前的数值交换状况。将这个成员变量更新为给定的更新后的值(update)若是当前值等于指望值(expect)时。
public final boolean weakCompareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
复制代码
相信一些小伙伴对此方法有点疑惑,由于若是是基于CAS交换的话,不必增长一个weak在方法名上,(同时让咱们想起来JAVA中的四种引用类型。。),这里官方就给出了解释:
weakCompareAndSet底层不会建立任何happen-before的保证,也就是不会对volatile字段操做的先后加入内存屏障。由于就没法保证多线程操做下对除了weakCompareAndSet操做的目标变量( 该目标变量必定是一个volatile变量 )之其余的变量读取和写入数据的正确性。
5.getAndUpdate(IntUnaryOperator updateFunction)
这个方法先很少说,直接上代码:
public final int getAndUpdate(IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get();
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(prev, next));
return prev;
}
复制代码
这里面是使用了循环进行更新值,利用的是以前的CAS操做判断以前的值与以后的值是不是一致的关系。而后进行更新操做。这里还使用了功能型接口IntUnaryOperator
。
整体来讲:AtomicXXX相关的类的操做都是大体相同的,都是使用的是无锁的CAS操做,对于性能方面可以有所提升,也不须要考虑线程阻塞的状况发生。对于多线程操做的状况下仍是很好的一个选择。