概要
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。
AtomicIntegerFieldUpdater
/*
* @(#)AtomicIntegerFieldUpdater.java 1.13 06/06/15
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.util.concurrent.atomic;
import sun.misc.Unsafe;
import java.lang.reflect.*;
/**
* A reflection-based utility that enables atomic updates to
* designated {@code volatile int} fields of designated classes.
* This class is designed for use in atomic data structures in which
* several fields of the same node are independently subject to atomic
* updates.
*
* <p>Note that the guarantees of the {@code compareAndSet}
* method in this class are weaker than in other atomic classes.
* Because this class cannot ensure that all uses of the field
* are appropriate for purposes of atomic access, it can
* guarantee atomicity only with respect to other invocations of
* {@code compareAndSet} and {@code set} on the same updater.
*
* @since 1.5
* @author Doug Lea
* @param <T> The type of the object holding the updatable field
*/
//抽象函数
public abstract class AtomicIntegerFieldUpdater<T> {
/**
* Creates and returns an updater for objects with the given field.
* The Class argument is needed to check that reflective types and
* generic types match.
*
* @param tclass the class of the objects holding the field
* @param fieldName the name of the field to be updated
* @return the updater
* @throws IllegalArgumentException if the field is not a
* volatile integer type
* @throws RuntimeException with a nested reflection-based
* exception if the class does not hold field or is the wrong type
*/
public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName);
}
/**
* Protected do-nothing constructor for use by subclasses.
*/
protected AtomicIntegerFieldUpdater() {
}
/**
* Atomically sets the field of the given object managed by this updater
* to the given updated value if the current value {@code ==} the
* expected value. This method is guaranteed to be atomic with respect to
* other calls to {@code compareAndSet} and {@code set}, but not
* necessarily with respect to other changes in the field.
*
* @param obj An object whose field to conditionally set
* @param expect the expected value
* @param update the new value
* @return true if successful
* @throws ClassCastException if {@code obj} is not an instance
* of the class possessing the field established in the constructor
*/
public abstract boolean compareAndSet(T obj, int expect, int update);
/**
* Atomically sets the field of the given object managed by this updater
* to the given updated value if the current value {@code ==} the
* expected value. This method is guaranteed to be atomic with respect to
* other calls to {@code compareAndSet} and {@code set}, but not
* necessarily with respect to other changes in the field.
*
* <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
* and does not provide ordering guarantees, so is only rarely an
* appropriate alternative to {@code compareAndSet}.
*
* @param obj An object whose field to conditionally set
* @param expect the expected value
* @param update the new value
* @return true if successful
* @throws ClassCastException if {@code obj} is not an instance
* of the class possessing the field established in the constructor
*/
public abstract boolean weakCompareAndSet(T obj, int expect, int update);
/**
* Sets the field of the given object managed by this updater to the
* given updated value. This operation is guaranteed to act as a volatile
* store with respect to subsequent invocations of {@code compareAndSet}.
*
* @param obj An object whose field to set
* @param newValue the new value
*/
public abstract void set(T obj, int newValue);
/**
* Eventually sets the field of the given object managed by this
* updater to the given updated value.
*
* @param obj An object whose field to set
* @param newValue the new value
* @since 1.6
*/
public abstract void lazySet(T obj, int newValue);
/**
* Gets the current value held in the field of the given object managed
* by this updater.
*
* @param obj An object whose field to get
* @return the current value
*/
public abstract int get(T obj);
/**
* Atomically sets the field of the given object managed by this updater
* to the given value and returns the old value.
*
* @param obj An object whose field to get and set
* @param newValue the new value
* @return the previous value
*/
public int getAndSet(T obj, int newValue) {
for (;;) {
int current = get(obj);
if (compareAndSet(obj, current, newValue))
return current;
}
}
/**
* Atomically increments by one the current value of the field of the
* given object managed by this updater.
*
* @param obj An object whose field to get and set
* @return the previous value
*/
public int getAndIncrement(T obj) {
for (;;) {
int current = get(obj);
int next = current + 1;
if (compareAndSet(obj, current, next))
return current;
}
}
/**
* Atomically decrements by one the current value of the field of the
* given object managed by this updater.
*
* @param obj An object whose field to get and set
* @return the previous value
*/
public int getAndDecrement(T obj) {
for (;;) {
int current = get(obj);
int next = current - 1;
if (compareAndSet(obj, current, next))
return current;
}
}
/**
* Atomically adds the given value to the current value of the field of
* the given object managed by this updater.
*
* @param obj An object whose field to get and set
* @param delta the value to add
* @return the previous value
*/
public int getAndAdd(T obj, int delta) {
for (;;) {
int current = get(obj);
int next = current + delta;
if (compareAndSet(obj, current, next))
return current;
}
}
/**
* Atomically increments by one the current value of the field of the
* given object managed by this updater.
*
* @param obj An object whose field to get and set
* @return the updated value
*/
public int incrementAndGet(T obj) {
for (;;) {
int current = get(obj);
int next = current + 1;
if (compareAndSet(obj, current, next))
return next;
}
}
/**
* Atomically decrements by one the current value of the field of the
* given object managed by this updater.
*
* @param obj An object whose field to get and set
* @return the updated value
*/
public int decrementAndGet(T obj) {
for (;;) {
int current = get(obj);
int next = current - 1;
if (compareAndSet(obj, current, next))
return next;
}
}
/**
* Atomically adds the given value to the current value of the field of
* the given object managed by this updater.
*
* @param obj An object whose field to get and set
* @param delta the value to add
* @return the updated value
*/
public int addAndGet(T obj, int delta) {
for (;;) {
int current = get(obj);
int next = current + delta;
if (compareAndSet(obj, current, next))
return next;
}
}
/**
* Standard hotspot implementation using intrinsics
*/
//具体的实现类
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(Class<T> tclass, String fieldName) {
Field field = null;
Class caller = null;
int modifiers = 0;
try {
field = tclass.getDeclaredField(fieldName); //得到具体的域 Field
caller = sun.reflect.Reflection.getCallerClass(3);
modifiers = field.getModifiers();
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
caller, tclass, null, modifiers);
sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
} catch(Exception ex) {
throw new RuntimeException(ex);
}
Class fieldt = field.getType();
if (fieldt != int.class)
throw new IllegalArgumentException("Must be integer type"); //域必须是Integer类型(校验)
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); //得到域的偏移
}
private void fullCheck(T obj) {
if (!tclass.isInstance(obj))
throw new ClassCastException();
if (cclass != null)
ensureProtectedAccess(obj);
}
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); //obj具体的调用对象
}
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);
}
private void ensureProtectedAccess(T obj) {
if (cclass.isInstance(obj)) {
return;
}
throw new RuntimeException(
new IllegalAccessException("Class " +
cclass.getName() +
" can not access a protected member of class " +
tclass.getName() +
" using an instance of " +
obj.getClass().getName()
)
);
}
}
}
AtomicLongFieldUpdater
/*
* @(#)AtomicLongFieldUpdater.java 1.14 06/06/15
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.util.concurrent.atomic;
import sun.misc.Unsafe;
import java.lang.reflect.*;
/**
* A reflection-based utility that enables atomic updates to
* designated {@code volatile long} fields of designated classes.
* This class is designed for use in atomic data structures in which
* several fields of the same node are independently subject to atomic
* updates.
*
* <p>Note that the guarantees of the {@code compareAndSet}
* method in this class are weaker than in other atomic classes.
* Because this class cannot ensure that all uses of the field
* are appropriate for purposes of atomic access, it can
* guarantee atomicity only with respect to other invocations of
* {@code compareAndSet} and {@code set} on the same updater.
*
* @since 1.5
* @author Doug Lea
* @param <T> The type of the object holding the updatable field
*/
public abstract class AtomicLongFieldUpdater<T> {
/**
* Creates and returns an updater for objects with the given field.
* The Class argument is needed to check that reflective types and
* generic types match.
*
* @param tclass the class of the objects holding the field
* @param fieldName the name of the field to be updated.
* @return the updater
* @throws IllegalArgumentException if the field is not a
* volatile long type.
* @throws RuntimeException with a nested reflection-based
* exception if the class does not hold field or is the wrong type.
*/
public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
if (AtomicLong.VM_SUPPORTS_LONG_CAS) //虚拟机是否支持CAS long 原子操作
return new CASUpdater<U>(tclass, fieldName);
else
return new LockedUpdater<U>(tclass, fieldName);
}
/**
* Protected do-nothing constructor for use by subclasses.
*/
protected AtomicLongFieldUpdater() {
}
/**
* Atomically sets the field of the given object managed by this updater
* to the given updated value if the current value {@code ==} the
* expected value. This method is guaranteed to be atomic with respect to
* other calls to {@code compareAndSet} and {@code set}, but not
* necessarily with respect to other changes in the field.
*
* @param obj An object whose field to conditionally set
* @param expect the expected value
* @param update the new value
* @return true if successful.
* @throws ClassCastException if {@code obj} is not an instance
* of the class possessing the field established in the constructor.
*/
public abstract boolean compareAndSet(T obj, long expect, long update);
/**
* Atomically sets the field of the given object managed by this updater
* to the given updated value if the current value {@code ==} the
* expected value. This method is guaranteed to be atomic with respect to
* other calls to {@code compareAndSet} and {@code set}, but not
* necessarily with respect to other changes in the field.
*
* <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
* and does not provide ordering guarantees, so is only rarely an
* appropriate alternative to {@code compareAndSet}.
*
* @param obj An object whose field to conditionally set
* @param expect the expected value
* @param update the new value
* @return true if successful.
* @throws ClassCastException if {@code obj} is not an instance
* of the class possessing the field established in the constructor.
*/
public abstract boolean weakCompareAndSet(T obj, long expect, long update);
/**
* Sets the field of the given object managed by this updater to the
* given updated value. This operation is guaranteed to act as a volatile
* store with respect to subsequent invocations of {@code compareAndSet}.
*
* @param obj An object whose field to set
* @param newValue the new value
*/
public abstract void set(T obj, long newValue);
/**
* Eventually sets the field of the given object managed by this
* updater to the given updated value.
*
* @param obj An object whose field to set
* @param newValue the new value
* @since 1.6
*/
public abstract void lazySet(T obj, long newValue);
/**
* Gets the current value held in the field of the given object managed
* by this updater.
*
* @param obj An object whose field to get
* @return the current value
*/
public abstract long get(T obj);
/**
* Atomically sets the field of the given object managed by this updater
* to the given value and returns the old value.
*
* @param obj An object whose field to get and set
* @param newValue the new value
* @return the previous value
*/
public long getAndSet(T obj, long newValue) {
for (;;) {
long current = get(obj);
if (compareAndSet(obj, current, newValue))
return current;
}
}
/**
* Atomically increments by one the current value of the field of the
* given object managed by this updater.
*
* @param obj An object whose field to get and set
* @return the previous value
*/
public long getAndIncrement(T obj) {
for (;;) {
long current = get(obj);
long next = current + 1;
if (compareAndSet(obj, current, next))
return current;
}
}
/**
* Atomically decrements by one the current value of the field of the
* given object managed by this updater.
*
* @param obj An object whose field to get and set
* @return the previous value
*/
public long getAndDecrement(T obj) {
for (;;) {
long current = get(obj);
long next = current - 1;
if (compareAndSet(obj, current, next))
return current;
}
}
/**
* Atomically adds the given value to the current value of the field of
* the given object managed by this updater.
*
* @param obj An object whose field to get and set
* @param delta the value to add
* @return the previous value
*/
public long getAndAdd(T obj, long delta) {
for (;;) {
long current = get(obj);
long next = current + delta;
if (compareAndSet(obj, current, next))
return current;
}
}
/**
* Atomically increments by one the current value of the field of the
* given object managed by this updater.
*
* @param obj An object whose field to get and set
* @return the updated value
*/
public long incrementAndGet(T obj) {
for (;;) {
long current = get(obj);
long next = current + 1;
if (compareAndSet(obj, current, next))
return next;
}
}
/**
* Atomically decrements by one the current value of the field of the
* given object managed by this updater.
*
* @param obj An object whose field to get and set
* @return the updated value
*/
public long decrementAndGet(T obj) {
for (;;) {
long current = get(obj);
long next = current - 1;
if (compareAndSet(obj, current, next))
return next;
}
}
/**
* Atomically adds the given value to the current value of the field of
* the given object managed by this updater.
*
* @param obj An object whose field to get and set
* @param delta the value to add
* @return the updated value
*/
public long addAndGet(T obj, long delta) {
for (;;) {
long current = get(obj);
long next = current + delta;
if (compareAndSet(obj, current, next))
return next;
}
}
private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
private static final Unsafe unsafe = Unsafe.getUnsafe();
private final long offset;
private final Class<T> tclass;
private final Class cclass;
CASUpdater(Class<T> tclass, String fieldName) {
Field field = null;
Class caller = null;
int modifiers = 0;
try {
field = tclass.getDeclaredField(fieldName); //得到File
caller = sun.reflect.Reflection.getCallerClass(3);
modifiers = field.getModifiers();
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
caller, tclass, null, modifiers);
sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
} catch(Exception ex) {
throw new RuntimeException(ex);
}
Class fieldt = field.getType();
if (fieldt != long.class)
throw new IllegalArgumentException("Must be long type"); //必须是volatile long
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); //得到域在对象里面的偏移
}
private void fullCheck(T obj) {
if (!tclass.isInstance(obj))
throw new ClassCastException();
if (cclass != null)
ensureProtectedAccess(obj);
}
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);
}
public boolean weakCompareAndSet(T obj, long expect, long update) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
return unsafe.compareAndSwapLong(obj, offset, expect, update);
}
public void set(T obj, long newValue) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
unsafe.putLongVolatile(obj, offset, newValue);
}
public void lazySet(T obj, long newValue) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
unsafe.putOrderedLong(obj, offset, newValue);
}
public long get(T obj) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
return unsafe.getLongVolatile(obj, offset);
}
private void ensureProtectedAccess(T obj) {
if (cclass.isInstance(obj)) {
return;
}
throw new RuntimeException (
new IllegalAccessException("Class " +
cclass.getName() +
" can not access a protected member of class " +
tclass.getName() +
" using an instance of " +
obj.getClass().getName()
)
);
}
}
//不支持CAS long 的原子操作就必须用lock
private static class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
private static final Unsafe unsafe = Unsafe.getUnsafe();
private final long offset;
private final Class<T> tclass;
private final Class cclass;
LockedUpdater(Class<T> tclass, String fieldName) {
Field field = null;
Class caller = null;
int modifiers = 0;
try {
field = tclass.getDeclaredField(fieldName); //得到Field
caller = sun.reflect.Reflection.getCallerClass(3);
modifiers = field.getModifiers();
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
caller, tclass, null, modifiers);
sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
} catch(Exception ex) {
throw new RuntimeException(ex);
}
Class fieldt = field.getType();
if (fieldt != long.class)
throw new IllegalArgumentException("Must be long 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); //得到域的偏移
}
private void fullCheck(T obj) {
if (!tclass.isInstance(obj))
throw new ClassCastException();
if (cclass != null)
ensureProtectedAccess(obj);
}
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);
}
}
private void ensureProtectedAccess(T obj) {
if (cclass.isInstance(obj)) {
return;
}
throw new RuntimeException (
new IllegalAccessException("Class " +
cclass.getName() +
" can not access a protected member of class " +
tclass.getName() +
" using an instance of " +
obj.getClass().getName()
)
);
}
}
}
AtomicReferenceFieldUpdater
/*
* @(#)AtomicReferenceFieldUpdater.java 1.15 06/06/15
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.util.concurrent.atomic;
import sun.misc.Unsafe;
import java.lang.reflect.*;
/**
* A reflection-based utility that enables atomic updates to
* designated {@code volatile} reference fields of designated
* classes. This class is designed for use in atomic data structures
* in which several reference fields of the same node are
* independently subject to atomic updates. For example, a tree node
* might be declared as
*
* <pre>
* class Node {
* private volatile Node left, right;
*
* private static final AtomicReferenceFieldUpdater<Node, Node> leftUpdater =
* AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
* private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater =
* AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
*
* Node getLeft() { return left; }
* boolean compareAndSetLeft(Node expect, Node update) {
* return leftUpdater.compareAndSet(this, expect, update);
* }
* // ... and so on
* }
* </pre>
*
* <p>Note that the guarantees of the {@code compareAndSet}
* method in this class are weaker than in other atomic classes.
* Because this class cannot ensure that all uses of the field
* are appropriate for purposes of atomic access, it can
* guarantee atomicity only with respect to other invocations of
* {@code compareAndSet} and {@code set} on the same updater.
*
* @since 1.5
* @author Doug Lea
* @param <T> The type of the object holding the updatable field
* @param <V> The type of the field
*/
//抽象类
public abstract class AtomicReferenceFieldUpdater<T, V> {
/**
* Creates and returns an updater for objects with the given field.
* The Class arguments are needed to check that reflective types and
* generic types match.
*
* @param tclass the class of the objects holding the field.
* @param vclass the class of the field
* @param fieldName the name of the field to be updated.
* @return the updater
* @throws IllegalArgumentException if the field is not a volatile reference type.
* @throws RuntimeException with a nested reflection-based
* exception if the class does not hold field or is the wrong type.
*/
public static <U, W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass, Class<W> vclass, String fieldName) {
return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass,
vclass,
fieldName);
}
/**
* Protected do-nothing constructor for use by subclasses.
*/
protected AtomicReferenceFieldUpdater() {
}
/**
* Atomically sets the field of the given object managed by this updater
* to the given updated value if the current value {@code ==} the
* expected value. This method is guaranteed to be atomic with respect to
* other calls to {@code compareAndSet} and {@code set}, but not
* necessarily with respect to other changes in the field.
*
* @param obj An object whose field to conditionally set
* @param expect the expected value
* @param update the new value
* @return true if successful.
*/
public abstract boolean compareAndSet(T obj, V expect, V update);
/**
* Atomically sets the field of the given object managed by this updater
* to the given updated value if the current value {@code ==} the
* expected value. This method is guaranteed to be atomic with respect to
* other calls to {@code compareAndSet} and {@code set}, but not
* necessarily with respect to other changes in the field.
*
* <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
* and does not provide ordering guarantees, so is only rarely an
* appropriate alternative to {@code compareAndSet}.
*
* @param obj An object whose field to conditionally set
* @param expect the expected value
* @param update the new value
* @return true if successful.
*/
public abstract boolean weakCompareAndSet(T obj, V expect, V update);
/**
* Sets the field of the given object managed by this updater to the
* given updated value. This operation is guaranteed to act as a volatile
* store with respect to subsequent invocations of {@code compareAndSet}.
*
* @param obj An object whose field to set
* @param newValue the new value
*/
public abstract void set(T obj, V newValue);
/**
* Eventually sets the field of the given object managed by this
* updater to the given updated value.
*
* @param obj An object whose field to set
* @param newValue the new value
* @since 1.6
*/
public abstract void lazySet(T obj, V newValue);
/**
* Gets the current value held in the field of the given object managed
* by this updater.
*
* @param obj An object whose field to get
* @return the current value
*/
public abstract V get(T obj);
/**
* Atomically sets the field of the given object managed by this updater
* to the given value and returns the old value.
*
* @param obj An object whose field to get and set
* @param newValue the new value
* @return the previous value
*/
public V getAndSet(T obj, V newValue) {
for (;;) {
V current = get(obj);
if (compareAndSet(obj, current, newValue))
return current;
}
}
private static final class AtomicReferenceFieldUpdaterImpl<T,V>
extends AtomicReferenceFieldUpdater<T,V> {
private static final Unsafe unsafe = Unsafe.getUnsafe();
private final long offset;
private final Class<T> tclass;
private final Class<V> vclass;
private final Class cclass;
/*
* Internal type checks within all update methods contain
* internal inlined optimizations checking for the common
* cases where the class is final (in which case a simple
* getClass comparison suffices) or is of type Object (in
* which case no check is needed because all objects are
* instances of Object). The Object case is handled simply by
* setting vclass to null in constructor. The targetCheck and
* updateCheck methods are invoked when these faster
* screenings fail.
*/
AtomicReferenceFieldUpdaterImpl(Class<T> tclass,
Class<V> vclass,
String fieldName) {
Field field = null;
Class fieldClass = null;
Class caller = null;
int modifiers = 0;
try {
field = tclass.getDeclaredField(fieldName); //得到field
caller = sun.reflect.Reflection.getCallerClass(3);
modifiers = field.getModifiers();
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
caller, tclass, null, modifiers);
sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
fieldClass = field.getType();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
if (vclass != fieldClass)
throw new ClassCastException();
if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type"); //必须是volatile
this.cclass = (Modifier.isProtected(modifiers) &&
caller != tclass) ? caller : null;
this.tclass = tclass;
if (vclass == Object.class)
this.vclass = null;
else
this.vclass = vclass;
offset = unsafe.objectFieldOffset(field); //得到域在对象内的偏移偏移
}
void targetCheck(T obj) {
if (!tclass.isInstance(obj))
throw new ClassCastException();
if (cclass != null)
ensureProtectedAccess(obj);
}
//校验
void updateCheck(T obj, V update) {
if (!tclass.isInstance(obj) ||
(update != null && vclass != null && !vclass.isInstance(update)))
throw new ClassCastException();
if (cclass != null)
ensureProtectedAccess(obj);
}
public boolean compareAndSet(T obj, V expect, V update) {
if (obj == null || obj.getClass() != tclass || cclass != null ||
(update != null && vclass != null &&
vclass != update.getClass()))
updateCheck(obj, update);
return unsafe.compareAndSwapObject(obj, offset, expect, update);
}
public boolean weakCompareAndSet(T obj, V expect, V update) {
// same implementation as strong form for now
if (obj == null || obj.getClass() != tclass || cclass != null ||
(update != null && vclass != null &&
vclass != update.getClass()))
updateCheck(obj, update);
return unsafe.compareAndSwapObject(obj, offset, expect, update);
}
public void set(T obj, V newValue) {
if (obj == null || obj.getClass() != tclass || cclass != null ||
(newValue != null && vclass != null &&
vclass != newValue.getClass()))
updateCheck(obj, newValue);
unsafe.putObjectVolatile(obj, offset, newValue);
}
public void lazySet(T obj, V newValue) {
if (obj == null || obj.getClass() != tclass || cclass != null ||
(newValue != null && vclass != null &&
vclass != newValue.getClass()))
updateCheck(obj, newValue);
unsafe.putOrderedObject(obj, offset, newValue);
}
public V get(T obj) {
if (obj == null || obj.getClass() != tclass || cclass != null)
targetCheck(obj);
return (V)unsafe.getObjectVolatile(obj, offset);
}
private void ensureProtectedAccess(T obj) {
if (cclass.isInstance(obj)) {
return;
}
throw new RuntimeException (
new IllegalAccessException("Class " +
cclass.getName() +
" can not access a protected member of class " +
tclass.getName() +
" using an instance of " +
obj.getClass().getName()
)
);
}
}
}
AtomicMarkableReference
/*
* @(#)AtomicMarkableReference.java 1.7 06/06/15
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.util.concurrent.atomic;
/**
* An {@code AtomicMarkableReference} maintains an object reference
* along with a mark bit, that can be updated atomically.
* <p>
* <p> Implementation note. This implementation maintains markable
* references by creating internal objects representing "boxed"
* [reference, boolean] pairs.
*
* @since 1.5
* @author Doug Lea
* @param <V> The type of object referred to by this reference
*/
public class AtomicMarkableReference<V> {
private static class ReferenceBooleanPair<T> {
private final T reference;
private final boolean bit; //标记
ReferenceBooleanPair(T r, boolean i) {
reference = r; bit = i;
}
}
private final AtomicReference<ReferenceBooleanPair<V>> atomicRef; //包装的引用对象
/**
* Creates a new {@code AtomicMarkableReference} with the given
* initial values.
*
* @param initialRef the initial reference
* @param initialMark the initial mark
*/
public AtomicMarkableReference(V initialRef, boolean initialMark) {
atomicRef = new AtomicReference<ReferenceBooleanPair<V>> (new ReferenceBooleanPair<V>(initialRef, initialMark));
}
/**
* Returns the current value of the reference.
*
* @return the current value of the reference
*/
public V getReference() {
return atomicRef.get().reference; //得到真正的ref
}
/**
* Returns the current value of the mark.
*
* @return the current value of the mark
*/
public boolean isMarked() {
return atomicRef.get().bit; //是否标记
}
/**
* Returns the current values of both the reference and the mark.
* Typical usage is {@code boolean[1] holder; ref = v.get(holder); }.
*
* @param markHolder an array of size of at least one. On return,
* {@code markholder[0]} will hold the value of the mark.
* @return the current value of the reference
*/
public V get(boolean[] markHolder) { //用参数来装标记(mark)
ReferenceBooleanPair<V> p = atomicRef.get();
markHolder[0] = p.bit;
return p.reference;
}
/**
* Atomically sets the value of both the reference and mark
* to the given update values if the
* current reference is {@code ==} to the expected reference
* and the current mark is equal to the expected mark.
*
* <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
* and does not provide ordering guarantees, so is only rarely an
* appropriate alternative to {@code compareAndSet}.
*
* @param expectedReference the expected value of the reference
* @param newReference the new value for the reference
* @param expectedMark the expected value of the mark
* @param newMark the new value for the mark
* @return true if successful
*/
public boolean weakCompareAndSet(V expectedReference,
V newReference,
boolean expectedMark,
boolean newMark) {
ReferenceBooleanPair<V> current = atomicRef.get();
return expectedReference == current.reference &&
expectedMark == current.bit &&
((newReference == current.reference && newMark == current.bit) ||
atomicRef.weakCompareAndSet(current,
new ReferenceBooleanPair<V>(newReference,
newMark)));
}
/**
* Atomically sets the value of both the reference and mark
* to the given update values if the
* current reference is {@code ==} to the expected reference
* and the current mark is equal to the expected mark.
*
* @param expectedReference the expected value of the reference
* @param newReference the new value for the reference
* @param expectedMark the expected value of the mark
* @param newMark the new value for the mark
* @return true if successful
*/
public boolean compareAndSet(V expectedReference,
V newReference,
boolean expectedMark,
boolean newMark) {
ReferenceBooleanPair<V> current = atomicRef.get();
//多重校验
return expectedReference == current.reference &&
expectedMark == current.bit &&
((newReference == current.reference && newMark == current.bit) ||
atomicRef.compareAndSet(current,new ReferenceBooleanPair<V>(newReference,
newMark)));
}
/**
* Unconditionally sets the value of both the reference and mark.
*
* @param newReference the new value for the reference
* @param newMark the new value for the mark
*/
public void set(V newReference, boolean newMark) {
ReferenceBooleanPair<V> current = atomicRef.get();
//有一个不相等(引用和标记),就要重新设置
if (newReference != current.reference || newMark != current.bit)
atomicRef.set(new ReferenceBooleanPair<V>(newReference, newMark));
}
/**
* Atomically sets the value of the mark to the given update value
* if the current reference is {@code ==} to the expected
* reference. Any given invocation of this operation may fail
* (return {@code false}) spuriously, but repeated invocation
* when the current value holds the expected value and no other
* thread is also attempting to set the value will eventually
* succeed.
*
* @param expectedReference the expected value of the reference
* @param newMark the new value for the mark
* @return true if successful
*/
//尝试标记,新要看ref是否相等
public boolean attemptMark(V expectedReference, boolean newMark) {
ReferenceBooleanPair<V> current = atomicRef.get();
return expectedReference == current.reference &&
(newMark == current.bit ||
atomicRef.compareAndSet
(current, new ReferenceBooleanPair<V>(expectedReference,
newMark)));
}
}
AtomicStampedReference
/*
* @(#)AtomicStampedReference.java 1.7 06/06/15
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.util.concurrent.atomic;
/**
* An {@code AtomicStampedReference} maintains an object reference
* along with an integer "stamp", that can be updated atomically.
*
* <p> Implementation note. This implementation maintains stamped
* references by creating internal objects representing "boxed"
* [reference, integer] pairs.
*
* @since 1.5
* @author Doug Lea
* @param <V> The type of object referred to by this reference
*/
public class AtomicStampedReference<V> {
private static class ReferenceIntegerPair<T> {
private final T reference;
private final int integer; //与AtomicMarkableReference类似
ReferenceIntegerPair(T r, int i) {
reference = r; integer = i;
}
}
private final AtomicReference<ReferenceIntegerPair<V>> atomicRef;
/**
* Creates a new {@code AtomicStampedReference} with the given
* initial values.
*
* @param initialRef the initial reference
* @param initialStamp the initial stamp
*/
public AtomicStampedReference(V initialRef, int initialStamp) {
atomicRef = new AtomicReference<ReferenceIntegerPair<V>>
(new ReferenceIntegerPair<V>(initialRef, initialStamp));
}
/**
* Returns the current value of the reference.
*
* @return the current value of the reference
*/
public V getReference() {
return atomicRef.get().reference;
}
/**
* Returns the current value of the stamp.
*
* @return the current value of the stamp
*/
public int getStamp() {
return atomicRef.get().integer;
}
/**
* Returns the current values of both the reference and the stamp.
* Typical usage is {@code int[1] holder; ref = v.get(holder); }.
*
* @param stampHolder an array of size of at least one. On return,
* {@code stampholder[0]} will hold the value of the stamp.
* @return the current value of the reference
*/
public V get(int[] stampHolder) {
ReferenceIntegerPair<V> p = atomicRef.get();
stampHolder[0] = p.integer;
return p.reference;
}
/**
* Atomically sets the value of both the reference and stamp
* to the given update values if the
* current reference is {@code ==} to the expected reference
* and the current stamp is equal to the expected stamp.
*
* <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
* and does not provide ordering guarantees, so is only rarely an
* appropriate alternative to {@code compareAndSet}.
*
* @param expectedReference the expected value of the reference
* @param newReference the new value for the reference
* @param expectedStamp the expected value of the stamp
* @param newStamp the new value for the stamp
* @return true if successful
*/
public boolean weakCompareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
ReferenceIntegerPair<V> current = atomicRef.get();
return expectedReference == current.reference &&
expectedStamp == current.integer &&
((newReference == current.reference &&
newStamp == current.integer) ||
atomicRef.weakCompareAndSet(current,
new ReferenceIntegerPair<V>(newReference,
newStamp)));
}
/**
* Atomically sets the value of both the reference and stamp
* to the given update values if the
* current reference is {@code ==} to the expected reference
* and the current stamp is equal to the expected stamp.
*
* @param expectedReference the expected value of the reference
* @param newReference the new value for the reference
* @param expectedStamp the expected value of the stamp
* @param newStamp the new value for the stamp
* @return true if successful
*/
public boolean compareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
ReferenceIntegerPair<V> current = atomicRef.get();
return expectedReference == current.reference &&
expectedStamp == current.integer &&
((newReference == current.reference &&
newStamp == current.integer) ||
atomicRef.compareAndSet(current,
new ReferenceIntegerPair<V>(newReference,
newStamp)));
}
/**
* Unconditionally sets the value of both the reference and stamp.
*
* @param newReference the new value for the reference
* @param newStamp the new value for the stamp
*/
public void set(V newReference, int newStamp) {
ReferenceIntegerPair<V> current = atomicRef.get();
if (newReference != current.reference || newStamp != current.integer)
atomicRef.set(new ReferenceIntegerPair<V>(newReference, newStamp));
}
/**
* Atomically sets the value of the stamp to the given update value
* if the current reference is {@code ==} to the expected
* reference. Any given invocation of this operation may fail
* (return {@code false}) spuriously, but repeated invocation
* when the current value holds the expected value and no other
* thread is also attempting to set the value will eventually
* succeed.
*
* @param expectedReference the expected value of the reference
* @param newStamp the new value for the stamp
* @return true if successful
*/
public boolean attemptStamp(V expectedReference, int newStamp) {
ReferenceIntegerPair<V> current = atomicRef.get();
return expectedReference == current.reference &&
(newStamp == current.integer ||
atomicRef.compareAndSet(current,
new ReferenceIntegerPair<V>(expectedReference,
newStamp)));
}
}
更多内容
2. Java多线程系列--“JUC原子类”02之 AtomicLong原子类
3. Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类
4. Java多线程系列--“JUC原子类”04之 AtomicReference原子类