同步数据结构之原子字段类
引言
接下来是原子类序章中我们提到的原子更新字段类,它们是AtomicLongFieldUpdater,AtomicIntegerFieldUpdater,AtomicReferenceFieldUpdater。其实就是了原子的更新一个引用类型的整形字段、long型字段、引用类型字段。
AtomicIntegerFieldUpdater
首先根据如下的类结构可见,它本身是一个抽象方法,提供了一个静态工厂方法newUpdater()来生成实例。
1 public abstract class AtomicIntegerFieldUpdater<T> { 2 3 @CallerSensitive 4 public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) { 5 return new AtomicIntegerFieldUpdaterImpl<U> 6 (tclass, fieldName, Reflection.getCallerClass()); 7 } 8 9 /** 10 * Protected do-nothing constructor for use by subclasses. 11 */ 12 protected AtomicIntegerFieldUpdater() { 13 } 14 .....
接着来看它的实现类,它的实现类AtomicIntegerFieldUpdaterImpl是它的一个私有静态内部类:
1 private static class AtomicIntegerFieldUpdaterImpl<T> 2 extends AtomicIntegerFieldUpdater<T> { 3 private static final Unsafe unsafe = Unsafe.getUnsafe(); 4 private final long offset; 5 private final Class<T> tclass; 6 private final Class<?> cclass; 7 8 AtomicIntegerFieldUpdaterImpl(final Class<T> tclass, 9 final String fieldName, 10 final Class<?> caller) { 11 final Field field; 12 final int modifiers; 13 try { 14 field = AccessController.doPrivileged( 15 new PrivilegedExceptionAction<Field>() { 16 public Field run() throws NoSuchFieldException { 17 return tclass.getDeclaredField(fieldName); 18 } 19 }); 20 modifiers = field.getModifiers(); 21 sun.reflect.misc.ReflectUtil.ensureMemberAccess( 22 caller, tclass, null, modifiers); 23 ClassLoader cl = tclass.getClassLoader(); 24 ClassLoader ccl = caller.getClassLoader(); 25 if ((ccl != null) && (ccl != cl) && 26 ((cl == null) || !isAncestor(cl, ccl))) { 27 sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); 28 } 29 } catch (PrivilegedActionException pae) { 30 throw new RuntimeException(pae.getException()); 31 } catch (Exception ex) { 32 throw new RuntimeException(ex); 33 } 34 35 Class<?> fieldt = field.getType(); 36 if (fieldt != int.class) 37 throw new IllegalArgumentException("Must be integer type"); 38 39 if (!Modifier.isVolatile(modifiers)) 40 throw new IllegalArgumentException("Must be volatile type"); 41 42 this.cclass = (Modifier.isProtected(modifiers) && 43 caller != tclass) ? caller : null; 44 this.tclass = tclass; 45 offset = unsafe.objectFieldOffset(field); 46 } 47 .....
从它的实例构造方法可见,它首先会对目标class及其指定的字段进行检测,主要是访问权限、数据类型是否是int,是否 是volatile修饰,最后当然还有通过unsafe获取目标字段的偏移量,为后面的CAS原子操作作准备。
从以上方法我们可以得出,要想使用AtomicIntegerFieldUpdater原子的更新一个对象的某个字段,必须满足以下条件:
- 调用者必须有对目标类的访问权限;
- 目标字段必须是整形int或者Integer;
- 目标字段必须是public修饰的;
- 目标字段必须是volatile修饰的。
另外,实现类AtomicIntegerFieldUpdaterImpl还实现了一些AtomicIntegerFieldUpdater的基础的原子更新的抽象方法:
1 public boolean compareAndSet(T obj, int expect, int update) { 2 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 3 return unsafe.compareAndSwapInt(obj, offset, expect, update); 4 } 5 6 public boolean weakCompareAndSet(T obj, int expect, int update) { 7 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 8 return unsafe.compareAndSwapInt(obj, offset, expect, update); 9 } 10 11 public void set(T obj, int newValue) { 12 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 13 unsafe.putIntVolatile(obj, offset, newValue); 14 } 15 16 public void lazySet(T obj, int newValue) { 17 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 18 unsafe.putOrderedInt(obj, offset, newValue); 19 } 20 21 public final int get(T obj) { 22 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 23 return unsafe.getIntVolatile(obj, offset); 24 } 25 26 public int getAndSet(T obj, int newValue) { 27 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 28 return unsafe.getAndSetInt(obj, offset, newValue); 29 } 30 31 public int getAndIncrement(T obj) { 32 return getAndAdd(obj, 1); 33 } 34 35 public int getAndDecrement(T obj) { 36 return getAndAdd(obj, -1); 37 } 38 39 public int getAndAdd(T obj, int delta) { 40 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 41 return unsafe.getAndAddInt(obj, offset, delta); 42 } 43 44 public int incrementAndGet(T obj) { 45 return getAndAdd(obj, 1) + 1; 46 } 47 48 public int decrementAndGet(T obj) { 49 return getAndAdd(obj, -1) - 1; 50 } 51 52 public int addAndGet(T obj, int delta) { 53 return getAndAdd(obj, delta) + delta; 54 }
这些方法和AtomicInteger提供的方法一致,不再熬述。剩下的其他的一些方法和AtomicInteger提供的原子更新方法几乎一样,都分为那四大原子更新方法,也不在一一列举。
AtomicLongFieldUpdater
再看AtomicLongFieldUpdater,它和AtomicIntegerFieldUpdater的结构基本一致,也是一个抽象方法,不同的是它是对long型字段的原子更新,而不是整形。
另外还有一个比较重要的区别就是,它的实现类有两个,根据平台是否支持8字节的CAS操作来选择不同的实现:
1 @CallerSensitive 2 public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) { 3 Class<?> caller = Reflection.getCallerClass(); 4 if (AtomicLong.VM_SUPPORTS_LONG_CAS) 5 return new CASUpdater<U>(tclass, fieldName, caller); 6 else 7 return new LockedUpdater<U>(tclass, fieldName, caller); 8 }
如果平台支持8字节的CAS操作,那么实现逻辑 CASUpdater就和AtomicIntegerFieldUpdater中的实现类似,也就是直接使用CAS操作达到原子操作的目的,如果平台不支持8字节的CAS操作,那么就使用内部加锁的方式实现对8字节的原子更新操作,如下所示为当平台不支持8字节的CAS操作时的内部加锁实现方式:
1 public boolean compareAndSet(T obj, long expect, long update) { 2 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 3 synchronized (this) { 4 long v = unsafe.getLong(obj, offset); 5 if (v != expect) 6 return false; 7 unsafe.putLong(obj, offset, update); 8 return true; 9 } 10 } 11 12 public boolean weakCompareAndSet(T obj, long expect, long update) { 13 return compareAndSet(obj, expect, update); 14 } 15 16 public void set(T obj, long newValue) { 17 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 18 synchronized (this) { 19 unsafe.putLong(obj, offset, newValue); 20 } 21 } 22 23 public void lazySet(T obj, long newValue) { 24 set(obj, newValue); 25 } 26 27 public long get(T obj) { 28 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 29 synchronized (this) { 30 return unsafe.getLong(obj, offset); 31 } 32 }
可见当不支持8字节的CAS操作时,JDK8采用的是synchronized锁实现。
AtomicLongFieldUpdater和AtomicIntegerFieldUpdater一样,可以对所操作的字段进行加减和更复杂的函数式运算,具体方法和AtomicLong类似,不再一一列举了。
AtomicReferenceFieldUpdater
最后再看AtomicReferenceFieldUpdater,它同样是一个抽象类,也是通过一个工厂方法生成原子更新器实例,同样它的实现方法也是通过CAS实现,所要操作的字段也必须是特定类型的public volatile修饰的。
AtomicReferenceFieldUpdater比 AtomicReference的原子更新操作更细粒度和更精确,它比AtomicReference这种直接更新整个对象要高效的多。
测试代码:
1 public class AtomicIntegerFieldUpdaterTest { 2 3 private static AtomicIntegerFieldUpdater<User> a = AtomicIntegerFieldUpdater 4 .newUpdater(User.class, "old"); 5 6 public static void main(String[] args) { 7 User user = new User("conan", 10); 8 System.out.println(a.getAndIncrement(user)); //10 9 System.out.println(a.get(user)); //11 10 } 11 12 public static class User { 13 private String name; 14 public volatile int old; 15 16 public User(String name, int old) { 17 this.name = name; 18 this.old = old; 19 } 20 21 public String getName() { 22 return name; 23 } 24 25 public int getOld() { 26 return old; 27 } 28 } 29 }

浙公网安备 33010602011771号