JUC并发包提供了一系列的原子操作类,这些类都是使用非阻塞算法(CAS)实现的,相比于使用锁来实现,这些原子操作类在性能上更好一些。
JUC并发包中包含有AtomicInteger、AtomicLong和AtomicBoolean等原子性操作类,它们的原理相似。
这里以AtomicLong为例进行说明,AtomicLong是原子性递增或者递减类,它是使用Unsafe来实现的。
AtomicLong通过CAS提供了非阻塞的原子性操作。
其源码如下:public class AtomicLong extends Number implements java.io.Serializable {
private static final long serialVersionUID = 1927816293512124184L;
// 1. 获取Unsafe实例 AtomicLong类是通过BootStarp类加载器进行加载的
private static final Unsafe unsafe = Unsafe.getUnsafe();
// 2. 存放变量value的偏移量
private static final long valueOffset;
// 3. 判断JVM是否支持Long类型无锁CAS
static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
private static native boolean VMSupportsCS8();
static {
try {
// 4. 获取value在AtomicLong中的偏移量
valueOffset = unsafe.objectFieldOffset
(AtomicLong.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
// 5. 实际变量值,声明为volatile是为了在多线程环境下保证其内存可见性,value是具体存放计数的变量。
private volatile long value;
// 6. 有参构造方法
public AtomicLong(long initialValue) {
value = initialValue;
}
// 7. 无参构造方法
public AtomicLong() {
}
// 8. 获取值
public final long get() {
return value;
}
// 9. 写入值
public final void set(long newValue) {
value = newValue;
}
public final void lazySet(long newValue) {
unsafe.putOrderedLong(this, valueOffset, newValue);
}
public final long getAndSet(long newValue) {
return unsafe.getAndSetLong(this, valueOffset, newValue);
}
// 调用unsafe的compareAndSwapLong方法,如果原子变量中的value值等于expect,则使用update值更新该值并返回true,否则返回false。
public final boolean compareAndSet(long expect, long update) {
return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
}
//同上
public final boolean weakCompareAndSet(long expect, long update) {
return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
}
// 调用unsafe方法,原子性设置value值为原始值+1,返回值为原始值
public final long getAndIncrement() {
return unsafe.getAndAddLong(this, valueOffset, 1L);
}
// 调用unsafe方法,原子性设置value值为原始值-1,返回值为原始值
public final long getAndDecrement() {
return unsafe.getAndAddLong(this, valueOffset, -1L);
}
// 调用unsafe方法,原子性设置value值加上delta,并返回
public final long getAndAdd(long delta) {
return unsafe.getAndAddLong(this, valueOffset, delta);
}
// 调用unsafe方法,原子性设置value值为原始值+1,返回值为递增后的值
public final long incrementAndGet() {
return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L;
}
// 调用unsafe方法,原子性设置value值为原始值-1,返回值为递减后的值
public final long decrementAndGet() {
return unsafe.getAndAddLong(this, valueOffset, -1L) - 1L;
}
// 调用unsafe方法,原子性设置value值为原始值 + delta,返回值为加操作后的值
public final long addAndGet(long delta) {
return unsafe.getAndAddLong(this, valueOffset, delta) + delta;
}
public final long getAndUpdate(LongUnaryOperator updateFunction) {
long prev, next;
do {
prev = get();
next = updateFunction.applyAsLong(prev);
} while (!compareAndSet(prev, next));
return prev;
}
public final long updateAndGet(LongUnaryOperator updateFunction) {
long prev, next;
do {
prev = get();
next = updateFunction.applyAsLong(prev);
} while (!compareAndSet(prev, next));
return next;
}
public final long getAndAccumulate(long x,
LongBinaryOperator accumulatorFunction) {
long prev, next;
do {
prev = get();
next = accumulatorFunction.applyAsLong(prev, x);
} while (!compareAndSet(prev, next));
return prev;
}
public final long accumulateAndGet(long x,
LongBinaryOperator accumulatorFunction) {
long prev, next;
do {
prev = get();
next = accumulatorFunction.applyAsLong(prev, x);
} while (!compareAndSet(prev, next));
return next;
}
public String toString() {
return Long.toString(get());
}
// 获取int类型的值
public int intValue() {
return (int)get();
}
// 获取long类型的值
public long longValue() {
return get();
}
// 获取float类型的值
public float floatValue() {
return (float)get();
}
// 获取double类型的值
public double doubleValue() {
return (double)get();
}
}
从源码中看出,AtomicLong的递增或递减方法都是通过调用Unsafe的getAndAddLong方法来实现操作。
getAndAddLong方法是个原子性操作,在这里它的第一个参数是AtomicLong实例的引用,第二个参数是value变量在AtomicLong中的偏移量,第三个参数是要设置的第二个变量的值。
使用AtomicLong的实例代码见thread20
关于AtomicInteger和AtomicBoolean与AtomicLong原理类似,就不多说了。
代码示例:import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
/**
* @ClassName: AtomicLongTest
* @Description: 使用AtomicLong统计0的个数
* @Author: liuhefei
* @Date: 2019/12/8
* @blog: https://www.imooc.com/u/1323320/articles
**/
public class AtomicLongTest {
//1. 创建Long类型原子计数器
private static AtomicLong atomicLong = new AtomicLong();
//private static AtomicInteger atomicInteger = new AtomicInteger();
//private static AtomicBoolean atomicBoolean = new AtomicBoolean();
//2. 创建数据源
private static Integer[] arrayOne = new Integer[]{0, 1, 4, 0, 9, 100, 0, 1000, 54, 60, 20, 12, 0};
private static Integer[] arrayTwo = new Integer[]{0, 100, 30, 4, 6, 0, 8, 87, 0, 23, 56, 0, 3, 6 , 10, 0};
public static void main(String[] args) throws InterruptedException {
//线程one统计arrayOne中0的个数
Thread threadOne = new Thread(new Runnable() {
@Override
public void run() {
int size = arrayOne.length;
for(int i = 0; i
if(arrayOne[i].intValue() == 0){
atomicLong.incrementAndGet(); //调用unsafe方法,原子性设置value值为原始值+1,并返回递增后的值
}
}
}
});
//线程two统计arrayTwo中0的个数
Thread threadTwo = new Thread(new Runnable() {
@Override
public void run() {
int size = arrayTwo.length;
for(int i = 0; i
if(arrayTwo[i].intValue() == 0){
atomicLong.incrementAndGet(); //调用unsafe方法,原子性设置value值为原始值+1,并返回递增后的值
}
}
}
});
//启动线程
threadOne.start();
threadTwo.start();
//等待线程执行完毕
threadOne.join();
threadTwo.join();
System.out.println("count 0 = " + atomicLong.get());
}
}
发文不易,请诸君且看且点赞,感谢你的支持!