本篇主要对AtomicReference、AtomicReferenceArray、AtomicReferenceFieldUpdater进行讲解,本博已经对AtomicInteger、AtomicIntegerArray、AtomicIntegerFieldUpdater源码进行了深入解析。其实这几个类原理都是类似的,不同的是针对的操作数据类型有差异。
演示示例:
首先,提供一个线程类,用来模拟多线程环境:
package com.securitit.serialize.atomics;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
public class AtomicReferenceThread extends Thread {
// AtomicReference实例.
private AtomicReference<String> atomicReference;
// AtomicReferenceArray实例.
private AtomicReferenceArray<String> atomicReferenceArray;
// AtomicReferenceFieldUpdater实例.
private AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterBean, String> atomicReferenceFieldUpdater;
// AtomicReferenceFieldUpdaterBean实例.
private AtomicReferenceFieldUpdaterBean atomicReferenceFieldUpdaterBean;
// CountDownLatch可以进行线程计数,到达指定计数时,可唤醒调用await方法的线程.
private CountDownLatch countDownLatch;
public AtomicReferenceThread(AtomicReference<String> atomicReference,
AtomicReferenceArray<String> atomicReferenceArray,
AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterBean, String> atomicReferenceFieldUpdater,
AtomicReferenceFieldUpdaterBean atomicReferenceFieldUpdaterBean, CountDownLatch countDownLatch) {
this.atomicReference = atomicReference;
this.atomicReferenceArray = atomicReferenceArray;
this.atomicReferenceFieldUpdater = atomicReferenceFieldUpdater;
this.atomicReferenceFieldUpdaterBean = atomicReferenceFieldUpdaterBean;
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
// 将atomicReference值重置为888.
atomicReference.getAndSet("888");
// 将AtomicReferenceArray值均重置为999.
for (int index = 0; index < atomicReferenceArray.length(); index++) {
atomicReferenceArray.getAndSet(index, "999");
}
// 将AtomicReferenceFieldUpdater值重置为000.
if (atomicReferenceFieldUpdater.compareAndSet(atomicReferenceFieldUpdaterBean, "1", "000")) {
System.out.println("AtomicReferenceFieldUpdater 更新成功.");
} else {
System.out.println("AtomicReferenceFieldUpdater 更新失败.");
}
countDownLatch.countDown();
}
}
然后,为AtomicReferenceFieldUpdater测试新建Bean类,类中只包含一个counter属性:
package com.securitit.serialize.atomics;
public class AtomicReferenceFieldUpdaterBean {
// 内部计数器.
public volatile String counter = "1";
public String getCounter() {
return counter;
}
public void setCounter(String counter) {
this.counter = counter;
}
}
最后,编写测试类,在开启多线程操作AtomicReference、AtomicReferenceArray、AtomicReferenceFieldUpdater,以模拟多线程环境:
package com.securitit.serialize.atomics;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
public class AtomicReferenceTester {
// AtomicReference实例.
private static AtomicReference<String> atomicReference;
// AtomicReferenceArray实例.
private static AtomicReferenceArray<String> atomicReferenceArray;
// AtomicReferenceFieldUpdater实例.
private static AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterBean, String> atomicReferenceFieldUpdater;
// AtomicReferenceFieldUpdaterBean实例.
private static AtomicReferenceFieldUpdaterBean atomicReferenceFieldUpdaterBean;
// CountDownLatch可以进行线程计数,到达指定计数时,可唤醒调用await方法的线程.
private static CountDownLatch countDownLatch = new CountDownLatch(4);
public static void main(String[] args) throws Exception {
// 初始化AtomicReference实例.
atomicReference = new AtomicReference<String>("1");
// 初始化AtomicReferenceArray实例.
atomicReferenceArray = new AtomicReferenceArray<String>(10);
// 初始化AtomicReferenceArray实例数组内部值.
for (int index = 0; index < atomicReferenceArray.length(); index++) {
// 用当前索引作为值.
atomicReferenceArray.set(index, index + "");
}
// 初始化AtomicReferenceFieldUpdater实例.
// 第一个参数引用类型类型Class,第二个参数为成员变量类型Class,第三个参数为成员变量名称.
atomicReferenceFieldUpdater = AtomicReferenceFieldUpdater.newUpdater(AtomicReferenceFieldUpdaterBean.class,
String.class, "counter");
// 初始化AtomicReferenceFieldUpdaterBean实例.
atomicReferenceFieldUpdaterBean = new AtomicReferenceFieldUpdaterBean();
atomicReferenceFieldUpdaterBean.setCounter("1");
// 启动多线程测试.
new AtomicReferenceThread(atomicReference, atomicReferenceArray, atomicReferenceFieldUpdater,
atomicReferenceFieldUpdaterBean, countDownLatch).start();
new AtomicReferenceThread(atomicReference, atomicReferenceArray, atomicReferenceFieldUpdater,
atomicReferenceFieldUpdaterBean, countDownLatch).start();
new AtomicReferenceThread(atomicReference, atomicReferenceArray, atomicReferenceFieldUpdater,
atomicReferenceFieldUpdaterBean, countDownLatch).start();
new AtomicReferenceThread(atomicReference, atomicReferenceArray, atomicReferenceFieldUpdater,
atomicReferenceFieldUpdaterBean, countDownLatch).start();
// 等待所有线程执行完毕.
countDownLatch.await();
// 输出AtomicReference的值.
System.out.println("AtomicReference:" + atomicReference.get());
// 输出AtomicReferenceArray数值.
for (int index = 0; index < atomicReferenceArray.length(); index++) {
if(index != 0) {
continue;
}
System.out.println("AtomicReferenceArray:" + atomicReferenceArray.get(index));
}
// 输出atomicReferenceFieldUpdaterBean的值.
System.out.println("AtomicReferenceFieldUpdater:" + atomicReferenceFieldUpdaterBean.getCounter());
}
}
输出结果:
AtomicReferenceFieldUpdater 更新失败.
AtomicReferenceFieldUpdater 更新失败.
AtomicReferenceFieldUpdater 更新失败.
AtomicReferenceFieldUpdater 更新成功.
AtomicReference:888
AtomicReferenceArray:999
AtomicReferenceFieldUpdater:000
从结果可以看出:
· AtomicReference可以成功更新类型变量的值。
· AtomicReferenceArray可以成功更新类型变量的值。
· AtonicReferenceFieldUpdater可以成功更新指定Bean的某属性。
源码分析:
实现基础:
AtomicReference:
// 用于存储Reference.
private volatile V value;
AtomicReferenceArray:
// 内存中初始位置.
private static final int base;
// 内存中偏移位置.
private static final int shift;
// 内存中偏移位置.
private static final long arrayFieldOffset;
// 存储ReferenceArray.
private final Object[] array;
AtomicReferenceFieldUpdater:
// 使用内部类AtomicReferenceFieldUpdaterImpl完成具体处理.
public static <U,W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass,
Class<W> vclass, String fieldName) {
return new AtomicReferenceFieldUpdaterImpl<U,W>
(tclass, vclass, fieldName, Reflection.getCallerClass());
}
基本方法:
AtomicReference:
// 获取对象.
public final V get();
// 设置对象.
public final void set(V newValue);
// 延迟设置对象.
public final void lazySet(V newValue);
// 先取值,再修改.
public final V getAndSet(V newValue);
// 先取值,再修改当前原值.
public final V getAndUpdate(UnaryOperator<V> updateFunction);
// 先修当前原值,再取值.
public final V updateAndGet(UnaryOperator<V> updateFunction);
// 使用BinaryOperator对当前值和第一个参数进行计算,并更新当前值.
public final V getAndAccumulate(V x, BinaryOperator<V> accumulatorFunction);
// 使用BinaryOperator对当前值和第一个参数进行计算,并更新当前值.
public final V accumulateAndGet(V x, BinaryOperator<V> accumulatorFunction);
AtomicReferenceArray:
// 获取数组长度.
public final int length();
// 获取指定索引的对象.
public final E get(int i);
// 指定索引位置设置为新值.
public final void set(int i, E newValue);
// 延迟.指定索引位置设置为新值.
public final void lazySet(int i, E newValue);
// 先取值,再赋值.
public final E getAndSet(int i, E newValue) ;
// 依赖CAS,进行比较替换.
public final boolean compareAndSet(int i, E expect, E update);
// 依赖CAS,进行比较替换.
public final boolean weakCompareAndSet(int i, E expect, E update);
// 先取值,再修改当前原值.
public final E getAndUpdate(int i, UnaryOperator<E> updateFunction);
// 先修当前原值,再取值.
public final E updateAndGet(int i, UnaryOperator<E> updateFunction);
// 使用BinaryOperator对当前值和第一个参数进行计算,并更新当前值.
public final E getAndAccumulate(int i, E x, BinaryOperator<E> accumulatorFunction);
// 使用BinaryOperator对当前值和第一个参数进行计算,并更新当前值.
public final E accumulateAndGet(int i, E x, BinaryOperator<E> accumulatorFunction);
AtomicReferenceArray:
// 依赖CAS,进行比较替换.
public abstract boolean compareAndSet(T obj, V expect, V update);
// 依赖CAS,进行比较替换.
public abstract boolean weakCompareAndSet(T obj, V expect, V update);
// 设置新值.
public abstract void set(T obj, V newValue);
// 延迟设置新值.
public abstract void lazySet(T obj, V newValue);
// 获取对象.
public abstract V get(T obj);
// 先取值,再赋值.
public V getAndSet(T obj, V newValue);
// 先取值,再修改当前原值.
public final V getAndUpdate(T obj, UnaryOperator<V> updateFunction);
// 先修当前原值,再取值.
public final V updateAndGet(T obj, UnaryOperator<V> updateFunction);
// 使用BinaryOperator对当前值和第一个参数进行计算,并更新当前值.
public final V getAndAccumulate(T obj, V x, BinaryOperator<V> accumulatorFunction);
// 使用BinaryOperator对当前值和第一个参数进行计算,并更新当前值.
public final V accumulateAndGet(T obj, V x, BinaryOperator<V> accumulatorFunction);
AtomicReference、AtomicReferenceArray、AtomicReferenceFieldUpdater使用方式与AtomicInteger、AtomicIntegerArray、AtomicIntegerFieldUpdater设计和使用方式大致类似,只要搞清楚其中一种类的操作方式,另一个也可以一样使用。
注:文中源码均来自于JDK1.8版本,不同版本间可能存在差异。
如果有哪里有不明白或不清楚的内容,欢迎留言哦!