skywang12345

导航

 

 

概要

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 }
View Code

 

下面分析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。 

 


更多内容

1. Java多线程系列--“JUC原子类”01之 框架

2. Java多线程系列--“JUC原子类”02之 AtomicLong原子类

3. Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类

4. Java多线程系列--“JUC原子类”04之 AtomicReference原子类

5. Java多线程系列目录(共xx篇)

posted on 2014-01-19 14:36  如果天空不死  阅读(12081)  评论(0编辑  收藏  举报