概要
AtomicIntegerFieldUpdater, AtomicLongFieldUpdater和AtomicReferenceFieldUpdater这3个修改类的成员的原子类型的原理和用法相似。本章以对基本类型的原子类进行介绍。内容包括:
AtomicLongFieldUpdater介绍和函数列表
AtomicLongFieldUpdater示例
AtomicLongFieldUpdater源码分析(基于JDK1.7.0_40)
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3514623.html
AtomicLongFieldUpdater介绍和函数列表
AtomicLongFieldUpdater可以对指定"类的 'volatile long'类型的成员"进行原子更新。它是基于反射原理实现的。
AtomicLongFieldUpdater函数列表
// 受保护的无操作构造方法,供子类使用。 protected AtomicLongFieldUpdater() // 以原子方式将给定值添加到此更新器管理的给定对象的字段的当前值。 long addAndGet(T obj, long delta) // 如果当前值 == 预期值,则以原子方式将此更新器所管理的给定对象的字段设置为给定的更新值。 abstract boolean compareAndSet(T obj, long expect, long update) // 以原子方式将此更新器管理的给定对象字段当前值减 1。 long decrementAndGet(T obj) // 获取此更新器管理的在给定对象的字段中保持的当前值。 abstract long get(T obj) // 以原子方式将给定值添加到此更新器管理的给定对象的字段的当前值。 long getAndAdd(T obj, long delta) // 以原子方式将此更新器管理的给定对象字段当前值减 1。 long getAndDecrement(T obj) // 以原子方式将此更新器管理的给定对象字段的当前值加 1。 long getAndIncrement(T obj) // 将此更新器管理的给定对象的字段以原子方式设置为给定值,并返回旧值。 long getAndSet(T obj, long newValue) // 以原子方式将此更新器管理的给定对象字段当前值加 1。 long incrementAndGet(T obj) // 最后将此更新器管理的给定对象的字段设置为给定更新值。 abstract void lazySet(T obj, long newValue) // 为对象创建并返回一个具有给定字段的更新器。 static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) // 将此更新器管理的给定对象的字段设置为给定更新值。 abstract void set(T obj, long newValue) // 如果当前值 == 预期值,则以原子方式将此更新器所管理的给定对象的字段设置为给定的更新值。 abstract boolean weakCompareAndSet(T obj, long expect, long update)
AtomicLongFieldUpdater示例
// LongTest.java的源码 import java.util.concurrent.atomic.AtomicLongFieldUpdater; public class LongFieldTest { public static void main(String[] args) { // 获取Person的class对象 Class cls = Person.class; // 新建AtomicLongFieldUpdater对象,传递参数是“class对象”和“long类型在类中对应的名称” AtomicLongFieldUpdater mAtoLong = AtomicLongFieldUpdater.newUpdater(cls, "id"); Person person = new Person(12345678L); // 比较person的"id"属性,如果id的值为12345678L,则设置为1000。 mAtoLong.compareAndSet(person, 12345678L, 1000); System.out.println("id="+person.getId()); } } class Person { volatile long id; public Person(long id) { this.id = id; } public void setId(long id) { this.id = id; } public long getId() { return id; } }
运行结果:
id=1000
AtomicLongFieldUpdater源码分析(基于JDK1.7.0_40)
AtomicLongFieldUpdater完整源码
1 /* 2 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20 * 21 * 22 * 23 */ 24 25 /* 26 * 27 * 28 * 29 * 30 * 31 * Written by Doug Lea with assistance from members of JCP JSR-166 32 * Expert Group and released to the public domain, as explained at 33 * http://creativecommons.org/publicdomain/zero/1.0/ 34 */ 35 36 package java.util.concurrent.atomic; 37 import java.lang.reflect.*; 38 import sun.misc.Unsafe; 39 import sun.reflect.CallerSensitive; 40 import sun.reflect.Reflection; 41 42 /** 43 * A reflection-based utility that enables atomic updates to 44 * designated {@code volatile} reference fields of designated 45 * classes. This class is designed for use in atomic data structures 46 * in which several reference fields of the same node are 47 * independently subject to atomic updates. For example, a tree node 48 * might be declared as 49 * 50 * <pre> {@code 51 * class Node { 52 * private volatile Node left, right; 53 * 54 * private static final AtomicReferenceFieldUpdater<Node, Node> leftUpdater = 55 * AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left"); 56 * private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater = 57 * AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right"); 58 * 59 * Node getLeft() { return left; } 60 * boolean compareAndSetLeft(Node expect, Node update) { 61 * return leftUpdater.compareAndSet(this, expect, update); 62 * } 63 * // ... and so on 64 * }}</pre> 65 * 66 * <p>Note that the guarantees of the {@code compareAndSet} 67 * method in this class are weaker than in other atomic classes. 68 * Because this class cannot ensure that all uses of the field 69 * are appropriate for purposes of atomic access, it can 70 * guarantee atomicity only with respect to other invocations of 71 * {@code compareAndSet} and {@code set} on the same updater. 72 * 73 * @since 1.5 74 * @author Doug Lea 75 * @param <T> The type of the object holding the updatable field 76 * @param <V> The type of the field 77 */ 78 public abstract class AtomicReferenceFieldUpdater<T, V> { 79 80 /** 81 * Creates and returns an updater for objects with the given field. 82 * The Class arguments are needed to check that reflective types and 83 * generic types match. 84 * 85 * @param tclass the class of the objects holding the field. 86 * @param vclass the class of the field 87 * @param fieldName the name of the field to be updated. 88 * @return the updater 89 * @throws IllegalArgumentException if the field is not a volatile reference type. 90 * @throws RuntimeException with a nested reflection-based 91 * exception if the class does not hold field or is the wrong type. 92 */ 93 @CallerSensitive 94 public static <U, W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass, Class<W> vclass, String fieldName) { 95 return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass, 96 vclass, 97 fieldName, 98 Reflection.getCallerClass()); 99 } 100 101 /** 102 * Protected do-nothing constructor for use by subclasses. 103 */ 104 protected AtomicReferenceFieldUpdater() { 105 } 106 107 /** 108 * Atomically sets the field of the given object managed by this updater 109 * to the given updated value if the current value {@code ==} the 110 * expected value. This method is guaranteed to be atomic with respect to 111 * other calls to {@code compareAndSet} and {@code set}, but not 112 * necessarily with respect to other changes in the field. 113 * 114 * @param obj An object whose field to conditionally set 115 * @param expect the expected value 116 * @param update the new value 117 * @return true if successful. 118 */ 119 public abstract boolean compareAndSet(T obj, V expect, V update); 120 121 /** 122 * Atomically sets the field of the given object managed by this updater 123 * to the given updated value if the current value {@code ==} the 124 * expected value. This method is guaranteed to be atomic with respect to 125 * other calls to {@code compareAndSet} and {@code set}, but not 126 * necessarily with respect to other changes in the field. 127 * 128 * <p>May <a href="package-summary.html#Spurious">fail spuriously</a> 129 * and does not provide ordering guarantees, so is only rarely an 130 * appropriate alternative to {@code compareAndSet}. 131 * 132 * @param obj An object whose field to conditionally set 133 * @param expect the expected value 134 * @param update the new value 135 * @return true if successful. 136 */ 137 public abstract boolean weakCompareAndSet(T obj, V expect, V update); 138 139 /** 140 * Sets the field of the given object managed by this updater to the 141 * given updated value. This operation is guaranteed to act as a volatile 142 * store with respect to subsequent invocations of {@code compareAndSet}. 143 * 144 * @param obj An object whose field to set 145 * @param newValue the new value 146 */ 147 public abstract void set(T obj, V newValue); 148 149 /** 150 * Eventually sets the field of the given object managed by this 151 * updater to the given updated value. 152 * 153 * @param obj An object whose field to set 154 * @param newValue the new value 155 * @since 1.6 156 */ 157 public abstract void lazySet(T obj, V newValue); 158 159 /** 160 * Gets the current value held in the field of the given object managed 161 * by this updater. 162 * 163 * @param obj An object whose field to get 164 * @return the current value 165 */ 166 public abstract V get(T obj); 167 168 /** 169 * Atomically sets the field of the given object managed by this updater 170 * to the given value and returns the old value. 171 * 172 * @param obj An object whose field to get and set 173 * @param newValue the new value 174 * @return the previous value 175 */ 176 public V getAndSet(T obj, V newValue) { 177 for (;;) { 178 V current = get(obj); 179 if (compareAndSet(obj, current, newValue)) 180 return current; 181 } 182 } 183 184 private static final class AtomicReferenceFieldUpdaterImpl<T,V> 185 extends AtomicReferenceFieldUpdater<T,V> { 186 private static final Unsafe unsafe = Unsafe.getUnsafe(); 187 private final long offset; 188 private final Class<T> tclass; 189 private final Class<V> vclass; 190 private final Class cclass; 191 192 /* 193 * Internal type checks within all update methods contain 194 * internal inlined optimizations checking for the common 195 * cases where the class is final (in which case a simple 196 * getClass comparison suffices) or is of type Object (in 197 * which case no check is needed because all objects are 198 * instances of Object). The Object case is handled simply by 199 * setting vclass to null in constructor. The targetCheck and 200 * updateCheck methods are invoked when these faster 201 * screenings fail. 202 */ 203 204 AtomicReferenceFieldUpdaterImpl(Class<T> tclass, 205 Class<V> vclass, 206 String fieldName, 207 Class<?> caller) { 208 Field field = null; 209 Class fieldClass = null; 210 int modifiers = 0; 211 try { 212 field = tclass.getDeclaredField(fieldName); 213 modifiers = field.getModifiers(); 214 sun.reflect.misc.ReflectUtil.ensureMemberAccess( 215 caller, tclass, null, modifiers); 216 sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); 217 fieldClass = field.getType(); 218 } catch (Exception ex) { 219 throw new RuntimeException(ex); 220 } 221 222 if (vclass != fieldClass) 223 throw new ClassCastException(); 224 225 if (!Modifier.isVolatile(modifiers)) 226 throw new IllegalArgumentException("Must be volatile type"); 227 228 this.cclass = (Modifier.isProtected(modifiers) && 229 caller != tclass) ? caller : null; 230 this.tclass = tclass; 231 if (vclass == Object.class) 232 this.vclass = null; 233 else 234 this.vclass = vclass; 235 offset = unsafe.objectFieldOffset(field); 236 } 237 238 void targetCheck(T obj) { 239 if (!tclass.isInstance(obj)) 240 throw new ClassCastException(); 241 if (cclass != null) 242 ensureProtectedAccess(obj); 243 } 244 245 void updateCheck(T obj, V update) { 246 if (!tclass.isInstance(obj) || 247 (update != null && vclass != null && !vclass.isInstance(update))) 248 throw new ClassCastException(); 249 if (cclass != null) 250 ensureProtectedAccess(obj); 251 } 252 253 public boolean compareAndSet(T obj, V expect, V update) { 254 if (obj == null || obj.getClass() != tclass || cclass != null || 255 (update != null && vclass != null && 256 vclass != update.getClass())) 257 updateCheck(obj, update); 258 return unsafe.compareAndSwapObject(obj, offset, expect, update); 259 } 260 261 public boolean weakCompareAndSet(T obj, V expect, V update) { 262 // same implementation as strong form for now 263 if (obj == null || obj.getClass() != tclass || cclass != null || 264 (update != null && vclass != null && 265 vclass != update.getClass())) 266 updateCheck(obj, update); 267 return unsafe.compareAndSwapObject(obj, offset, expect, update); 268 } 269 270 public void set(T obj, V newValue) { 271 if (obj == null || obj.getClass() != tclass || cclass != null || 272 (newValue != null && vclass != null && 273 vclass != newValue.getClass())) 274 updateCheck(obj, newValue); 275 unsafe.putObjectVolatile(obj, offset, newValue); 276 } 277 278 public void lazySet(T obj, V newValue) { 279 if (obj == null || obj.getClass() != tclass || cclass != null || 280 (newValue != null && vclass != null && 281 vclass != newValue.getClass())) 282 updateCheck(obj, newValue); 283 unsafe.putOrderedObject(obj, offset, newValue); 284 } 285 286 public V get(T obj) { 287 if (obj == null || obj.getClass() != tclass || cclass != null) 288 targetCheck(obj); 289 return (V)unsafe.getObjectVolatile(obj, offset); 290 } 291 292 private void ensureProtectedAccess(T obj) { 293 if (cclass.isInstance(obj)) { 294 return; 295 } 296 throw new RuntimeException( 297 new IllegalAccessException("Class " + 298 cclass.getName() + 299 " can not access a protected member of class " + 300 tclass.getName() + 301 " using an instance of " + 302 obj.getClass().getName() 303 ) 304 ); 305 } 306 } 307 }
下面分析LongFieldTest.java的流程。
1. newUpdater()
newUpdater()的源码如下:
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); }
说明:newUpdater()的作用是获取一个AtomicIntegerFieldUpdater类型的对象。
它实际上返回的是CASUpdater对象,或者LockedUpdater对象;具体返回哪一个类取决于JVM是否支持long类型的CAS函数。CASUpdater和LockedUpdater都是AtomicIntegerFieldUpdater的子类,它们的实现类似。下面以CASUpdater来进行说明。
CASUpdater类的源码如下:
public boolean compareAndSet(T obj, long expect, long update) { if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); return unsafe.compareAndSwapLong(obj, offset, expect, update); }
说明:它实际上是通过CAS函数操作。如果类的long对象的值是expect,则设置它的值为update。
更多内容
2. Java多线程系列--“JUC原子类”02之 AtomicLong原子类
3. Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类