AtomicReference、AtomicReferenceArray、AtomicReferenceFieldUpdater 深入源码解析

  本篇主要对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版本,不同版本间可能存在差异。

  如果有哪里有不明白或不清楚的内容,欢迎留言哦!

猜你喜欢

转载自blog.csdn.net/securitit/article/details/106834580