Java concurrency之AtomicLongFieldUpdater原子类_动力节点Java学院整理

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

 /*
  * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  *
  *
  *
  *
  *
  *
  *
  *
  *
  *
  *
  *
  *
  *
  *
  *
  *
  *
  *
  *
  */
 /*
  *
  *
  *
  *
  *
  * Written by Doug Lea with assistance from members of JCP JSR-
  * Expert Group and released to the public domain,as explained at
  * http://creativecommons.org/publicdomain/zero/./
  */
 package java.util.concurrent.atomic;
 import java.lang.reflect.*;
 import sun.misc.Unsafe;
 import sun.reflect.CallerSensitive;
 import sun.reflect.Reflection;
 /**
  * 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> {@code
  * 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,"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 .
  * @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.
    */
   @CallerSensitive
   public static <U,W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass,Class<W> vclass,String fieldName) {
     return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass,vclass,fieldName,Reflection.getCallerClass());
   }
   /**
   * 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" rel="external nofollow" >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 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,Class<?> caller) {
       Field field = null;
       Class fieldClass = null;
       int modifiers = 0;
       try {
         field = tclass.getDeclaredField(fieldName);
         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");
       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 update) {
       if (obj == null || obj.getClass() != tclass || cclass != null ||
         (update != null && vclass != null &&
         vclass != update.getClass()))
         updateCheck(obj,update);
       return unsafe.compareAndSwapObject(obj,offset,update);
     }
     public boolean weakCompareAndSet(T obj,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);
     }
     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,newValue);
     }
     public void lazySet(T obj,newValue);
       unsafe.putOrderedObject(obj,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()
         )
       );
     }
   }
 }

   下面分析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,caller);
  else
    return new LockedUpdater<U>(tclass,caller);
}

说明:newUpdater()的作用是获取一个AtomicIntegerFieldUpdater类型的对象。

它实际上返回的是CASUpdater对象,或者LockedUpdater对象;具体返回哪一个类取决于JVM是否支持long类型的CAS函数。CASUpdater和LockedUpdater都是AtomicIntegerFieldUpdater的子类,它们的实现类似。下面以CASUpdater来进行说明。 

CASUpdater类的源码如下:

public boolean compareAndSet(T obj,long update) {
  if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
  return unsafe.compareAndSwapLong(obj,update);
}

说明:它实际上是通过CAS函数操作。如果类的long对象的值是expect,则设置它的值为update。 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


本文从从Bitcask存储模型讲起,谈轻量级KV系统设计与实现。从来没有最好的K-V系统,只有最适合应用业务实际场景的系统,做任何的方案选择,要结合业务当前的实际情况综合权衡,有所取有所舍。
内部的放到gitlab pages的博客,需要统计PV,不蒜子不能准确统计,原因在于gitlab的host设置了strict-origin-when-cross-origin, 导致不蒜子不能正确获取referer,从而PV只能统计到网站的PV。 为了方便统计页面的PV,这里简单的写了一个java程
PCM 自然界中的声音非常复杂,波形极其复杂,通常我们采用的是脉冲代码调制编码,即PCM编码。PCM通过抽样、量化、编码三个步骤将连续变化的模拟信号转换为数字编码。 采样率 采样频率,也称为采样速度或者采样率,定义了每秒从连续信号中提取并组成离散信号的采样个数,它用赫兹(Hz)来表示。采样频率的倒数
本文介绍如何离线生成sst并在线加载,提供一种用rocksdb建立分布式kv系统替换mongodb的思路
验证用户输入是否正确是我们应用程序中的常见功能。Spring提供了`@Valid`和@`Validated`两个注解来实现验证功能,本文详细介绍 [@Valid]和[@Validated]注解的区别 。
引入pdf2dom &lt;dependency&gt; &lt;groupId&gt;net.sf.cssbox&lt;/groupId&gt; &lt;artifactId&gt;pdf2dom&lt;/artifactId&gt; &lt;version&gt;1.8&lt;/version&
grafana 是一款非常优秀的可视化报表工具,有设计精良的可视化工具,今天来聊一聊如何将grafana集成到自己的应用中。 原理是: grafana允许iframe访问,开启auth.proxy, java 后端鉴权后代理grafana 前端通过iframe访问后端代理过的grafana graf
介绍 Call Graph是一款IDEA插件,用于可视化基于IntelliJ平台的IDE的函数调用图。 这个插件的目标是让代码更容易理解,有助于读懂和调试代码。当前只支持Java。针对Typescript、Javascript或Python工具,可以使用作者的另外一款工具Codemap(https:
原理 通过线程安全findAndModify 实现锁 实现 定义锁存储对象: /** * mongodb 分布式锁 */ @Data @NoArgsConstructor @AllArgsConstructor @Document(collection = &quot;distributed-loc
Singleton 单例模式 单例模式是确保每个应用程序只存在一个实例的机制。默认情况下,Spring将所有bean创建为单例。 你用@Autowired获取的bean,全局唯一。 @RestController public class LibraryController { @Autowired
pipeline 分布式任务调度器 目标: 基于docker的布式任务调度器, 比quartzs,xxl-job 更强大的分布式任务调度器。 可以将要执行的任务打包为docker镜像,或者选择已有镜像,自定义脚本程序,通过pipeline框架来实现调度。 开源地址: https://github.c
python训练的模型,转换为onnx模型后,用python代码可以方便进行推理,但是java代码如何实现呢? 首先ONNX 推理,可以使用`onnxruntime` ```xml com.microsoft.onnxruntime onnxruntime 1.15.1 ``` 另外,训练的模型需要
要获取内网地址,可以尝试连接到10.255.255.255:1。如果连接成功,获取本地套接字的地址信息就是当前的内网IP。 python实现: ```python import socket def extract_ip(): st = socket.socket(socket.AF_INET, s
为什么要有索引 gremlin 其实是一个逐级过滤的运行机制,比如下面的一个简单的gremlin查询语句: g.V().hasLabel(&quot;label&quot;).has(&quot;prop&quot;,&quot;value&quot;) 运行原理就是: 找出所有的顶点V 然后过滤出
最近在分析一个应用中的某个接口的耗时情况时,发现一个看起来极其普通的对象创建操作,竟然每次需要消耗 8ms 左右时间,分析后发现这个对象可以通过对象池模式进行优化,优化后此步耗时仅有 0.01ms。
点赞再看,动力无限。Hello world : ) 微信搜「 程序猿阿朗 」。 本文 Github.com/niumoo/JavaNotes 和 未读代码网站 已经收录,有很多知识点和系列文章。 此篇文章介绍 Java JMX 技术的相关概念和具体的使用方式。 当前文章属于Java 性能分析优化系列
如何将Java JAR 转化为 win/mac/linux 独立可执行程序?不需要预装 JRE 运行?
点赞再看,动力无限。 微信搜「 程序猿阿朗 」。 本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章。 Java 19 在2022 年 9 月 20 日正式发布,Java 19 不是一个长期支持版本,直到 2023 年 3 月它将被 JD
点赞再看,动力无限。Hello world : ) 微信搜「 程序猿阿朗 」。 本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章。 前言 Java 反编译,一听可能觉得高深莫测,其实反编译并不是什么特别高级的操作,Java 对于 Cla
JSON 对于开发者并不陌生,如今的 WEB 服务、移动应用、甚至物联网大多都是以 **JSON** 作为数据交换的格式。学习 JSON 格式的操作工具对开发者来说是必不可少的。这篇文章将介绍如何使用 **Jackson** 开源工具库对 JSON 进行常见操作。