Java多线程系列--“JUC原子类”05之 AtomicLongFieldUpdater原子类

 

概要

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完整源码

Java多线程系列--“JUC原子类”05之 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篇)

你可能感兴趣的:(AtomicLong)