在使用多线程并发编程的时,经常会遇到对共享变量修改操作。此时我们可以选择ConcurrentHashMap,ConcurrentLinkedQueue来进行安全地存储数据。但如果单单是涉及状态的修改,线程执行顺序问题,使用Atomic开头的原子组件或者ReentrantLock、CyclicBarrier之类的同步组件,会是更好的选择,下面将一一介绍它们的原理和用法
原子组件的实现原理CAS
AtomicBoolean、AtomicIntegerArray等原子组件的用法、
同步组件的实现原理
ReentrantLock、CyclicBarrier等同步组件的用法
原子组件的实现原理CAS
cas的底层实现可以看下之前写的一篇文章:详解锁原理,synchronized、volatile+cas底层实现[1]
应用场景
可用来实现变量、状态在多线程下的原子性操作
可用于实现同步锁(ReentrantLock)
原子组件
原子组件的原子性操作是靠使用cas来自旋操作volatile变量实现的
volatile的类型变量保证变量被修改时,其他线程都能看到最新的值
cas则保证value的修改操作是原子性的,不会被中断
基本类型原子类
AtomicBoolean //布尔类型
AtomicInteger //正整型数类型
AtomicLong //长整型类型
使用示例
public static void main(String[] args) throws Exception {
AtomicBoolean atomicBoolean = new AtomicBoolean(false);
//异步线程修改atomicBoolean
CompletableFuture<Void> future = CompletableFuture.runAsync(() ->{
try {
Thread.sleep(1000); //保证异步线程是在主线程之后修改atomicBoolean为false
atomicBoolean.set(false);
}catch (Exception e){
throw new RuntimeException(e);
}
});
atomicBoolean.set(true);
future.join();
System.out.println("boolean value is:"+atomicBoolean.get());
}
—————输出结果——————
boolean value is:false
引用类原子类
AtomicReference
//加时间戳版本的引用类原子类
AtomicStampedReference
//相当于AtomicStampedReference,AtomicMarkableReference关心的是
//变量是否还是原来变量,中间被修改过也无所谓
AtomicMarkableReference
AtomicReference的源码如下,它内部定义了一个volatile V value,并借助VarHandle(具体子类是FieldInstanceReadWrite)实现原子操作,MethodHandles会帮忙计算value在类的偏移位置,最后在VarHandle调用Unsafe.public final native boolean compareAndSetReference(Object o, long offset, Object expected, Object x)方法原子修改对象的属性