`
春花秋月何时了
  • 浏览: 39558 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

同步数据结构之原子字段类

 
阅读更多

引言

接下来是原子类序章中我们提到的原子更新字段类,它们是AtomicLongFieldUpdater,AtomicIntegerFieldUpdater,AtomicReferenceFieldUpdater。其实就是了原子的更新一个引用类型的整形字段、long型字段、引用类型字段。

 

AtomicIntegerFieldUpdater

首先根据如下的类结构可见,它本身是一个抽象方法,提供了一个静态工厂方法newUpdater()来生成实例。

public abstract class AtomicIntegerFieldUpdater<T> {

@CallerSensitive
public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
	return new AtomicIntegerFieldUpdaterImpl<U>
		(tclass, fieldName, Reflection.getCallerClass());
}

/**
 * Protected do-nothing constructor for use by subclasses.
 */
protected AtomicIntegerFieldUpdater() {
}
.....

 接着来看它的实现类,它的实现类AtomicIntegerFieldUpdaterImpl是它的一个私有静态内部类:

private static class AtomicIntegerFieldUpdaterImpl<T>
	extends AtomicIntegerFieldUpdater<T> {
		private static final Unsafe unsafe = Unsafe.getUnsafe();
		private final long offset;
		private final Class<T> tclass;
		private final Class<?> cclass;

		AtomicIntegerFieldUpdaterImpl(final Class<T> tclass,
								  final String fieldName,
								  final Class<?> caller) {
		final Field field;
		final int modifiers;
		try {
			field = AccessController.doPrivileged(
				new PrivilegedExceptionAction<Field>() {
					public Field run() throws NoSuchFieldException {
						return tclass.getDeclaredField(fieldName);
					}
				});
			modifiers = field.getModifiers();
			sun.reflect.misc.ReflectUtil.ensureMemberAccess(
				caller, tclass, null, modifiers);
			ClassLoader cl = tclass.getClassLoader();
			ClassLoader ccl = caller.getClassLoader();
			if ((ccl != null) && (ccl != cl) &&
				((cl == null) || !isAncestor(cl, ccl))) {
			  sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
			}
		} catch (PrivilegedActionException pae) {
			throw new RuntimeException(pae.getException());
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}

		Class<?> fieldt = field.getType();
		if (fieldt != int.class)
			throw new IllegalArgumentException("Must be integer type");

		if (!Modifier.isVolatile(modifiers))
			throw new IllegalArgumentException("Must be volatile type");

		this.cclass = (Modifier.isProtected(modifiers) &&
					   caller != tclass) ? caller : null;
		this.tclass = tclass;
		offset = unsafe.objectFieldOffset(field);
	}
.....

从它的实例构造方法可见,它首先会对目标class及其指定的字段进行检测,主要是访问权限、数据类型是否是int,是否 是volatile修饰,最后当然还有通过unsafe获取目标字段的偏移量,为后面的CAS原子操作作准备。

从以上方法我们可以得出,要想使用AtomicIntegerFieldUpdater原子的更新一个对象的某个字段,必须满足以下条件:

  1. 调用者必须有对目标类的访问权限;
  2. 目标字段必须是整形int或者Integer;
  3. 目标字段必须是public修饰的;
  4. 目标字段必须是volatile修饰的。

另外,实现类AtomicIntegerFieldUpdaterImpl还实现了一些AtomicIntegerFieldUpdater的基础的原子更新的抽象方法:

public boolean compareAndSet(T obj, int expect, int update) {
	if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
	return unsafe.compareAndSwapInt(obj, offset, expect, update);
}

public boolean weakCompareAndSet(T obj, int expect, int update) {
	if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
	return unsafe.compareAndSwapInt(obj, offset, expect, update);
}

public void set(T obj, int newValue) {
	if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
	unsafe.putIntVolatile(obj, offset, newValue);
}

public void lazySet(T obj, int newValue) {
	if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
	unsafe.putOrderedInt(obj, offset, newValue);
}

public final int get(T obj) {
	if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
	return unsafe.getIntVolatile(obj, offset);
}

public int getAndSet(T obj, int newValue) {
	if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
	return unsafe.getAndSetInt(obj, offset, newValue);
}

public int getAndIncrement(T obj) {
	return getAndAdd(obj, 1);
}

public int getAndDecrement(T obj) {
	return getAndAdd(obj, -1);
}

public int getAndAdd(T obj, int delta) {
	if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
	return unsafe.getAndAddInt(obj, offset, delta);
}

public int incrementAndGet(T obj) {
	return getAndAdd(obj, 1) + 1;
}

public int decrementAndGet(T obj) {
	 return getAndAdd(obj, -1) - 1;
}

public int addAndGet(T obj, int delta) {
	return getAndAdd(obj, delta) + delta;
}

 这些方法和AtomicInteger提供的方法一致,不再熬述。剩下的其他的一些方法和AtomicInteger提供的原子更新方法几乎一样,都分为那四大原子更新方法,也不在一一列举。

 

AtomicLongFieldUpdater

再看AtomicLongFieldUpdater,它和AtomicIntegerFieldUpdater的结构基本一致,也是一个抽象方法,不同的是它是对long型字段的原子更新,而不是整形。

 

另外还有一个比较重要的区别就是,它的实现类有两个,根据平台是否支持8字节的CAS操作来选择不同的实现:

@CallerSensitive
public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
	Class<?> caller = Reflection.getCallerClass();
	if (AtomicLong.VM_SUPPORTS_LONG_CAS)
		return new CASUpdater<U>(tclass, fieldName, caller);
	else
		return new LockedUpdater<U>(tclass, fieldName, caller);
}

如果平台支持8字节的CAS操作,那么实现逻辑 CASUpdater就和AtomicIntegerFieldUpdater中的实现类似,也就是直接使用CAS操作达到原子操作的目的,如果平台不支持8字节的CAS操作,那么就使用内部加锁的方式实现对8字节的原子更新操作,如下所示为当平台不支持8字节的CAS操作时的内部加锁实现方式:

public boolean compareAndSet(T obj, long expect, long update) {
	if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
	synchronized (this) {
		long v = unsafe.getLong(obj, offset);
		if (v != expect)
			return false;
		unsafe.putLong(obj, offset, update);
		return true;
	}
}

public boolean weakCompareAndSet(T obj, long expect, long update) {
	return compareAndSet(obj, expect, update);
}

public void set(T obj, long newValue) {
	if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
	synchronized (this) {
		unsafe.putLong(obj, offset, newValue);
	}
}

public void lazySet(T obj, long newValue) {
	set(obj, newValue);
}

public long get(T obj) {
	if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
	synchronized (this) {
		return unsafe.getLong(obj, offset);
	}
}

可见当不支持8字节的CAS操作时,JDK8采用的是synchronized锁实现。

 

AtomicLongFieldUpdater和AtomicIntegerFieldUpdater一样,可以对所操作的字段进行加减和更复杂的函数式运算,具体方法和AtomicLong类似,不再一一列举了。

 

AtomicReferenceFieldUpdater

最后再看AtomicReferenceFieldUpdater,它同样是一个抽象类,也是通过一个工厂方法生成原子更新器实例,同样它的实现方法也是通过CAS实现,所要操作的字段也必须是特定类型的public volatile修饰的。

 

AtomicReferenceFieldUpdater比 AtomicReference的原子更新操作更细粒度和更精确,它比AtomicReference这种直接更新整个对象要高效的多。

 

测试代码:

public class AtomicIntegerFieldUpdaterTest {

    private static AtomicIntegerFieldUpdater<User> a = AtomicIntegerFieldUpdater
            .newUpdater(User.class, "old");

    public static void main(String[] args) {
        User user = new User("conan", 10);
        System.out.println(a.getAndIncrement(user)); //10
        System.out.println(a.get(user)); //11
    }

    public static class User {
        private String name;
        public volatile int old;

        public User(String name, int old) {
            this.name = name;
            this.old = old;
        }

        public String getName() {
            return name;
        }

        public int getOld() {
            return old;
        }
    }
}

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics