侧边栏壁纸
博主头像
孔子说JAVA博主等级

成功只是一只沦落在鸡窝里的鹰,成功永远属于自信且有毅力的人!

  • 累计撰写 292 篇文章
  • 累计创建 132 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

Java并发编程之原子操作类AtomicLongFieldUpdater实战详解

孔子说JAVA
2022-06-15 / 0 评论 / 0 点赞 / 60 阅读 / 20,583 字 / 正在检测是否收录...

并发编程原子类完整教程:Java并发编程之原子操作类实战教程

AtomicLongFieldUpdater 是一个基于反射的工具类(原子操作),它能对指定类的 指定的volatile引用字段 进行 原子更新,需要注意的是这个字段不能是private的。简单理解就是对某个类中,被volatile修饰的字段进行原子更新。

  • AtomicLongFieldUpdater 是 Doug Lea 在Java 5中写的atomic classes 中Filed Updater的一部分,本质上是volatile字段的包装器。
  • ⼀个类中的volatile成员属性获取值、设定为某个值的这两个操作是⾮原⼦的,若想将其变为原⼦操作,可以通过 AtomicLongFieldUpdater 来实现。
  • AtomicReferenceFieldUpdater 是针对引用类型属性,而 AtomicLongFieldUpdater 是针对长整形的属性。
  • AtomicLongFieldUpdater 在高并发场景下,自旋 CAS 长时间失败会导致 CPU 飙升。

1、AtomicLongFieldUpdater 的使用条件

1.1 应用场景

如果一个类是自己编写的,可以在编写的时候把成员变量定义为Atomic类型。但如果是一个已经有的类,在不能更改其源代码的情况下,要想实现对其成员变量的原子操作,就需要AtomicIntegerFieldUpdater、AtomicLongFieldUpdater 和 AtomicReferenceFieldUpdater。

1.2 使用条件

原子更新器 AtomicLongFieldUpdater 的使用存在比较苛刻的条件:

  • 只能是实例变量,不能是类变量,也就是说不能加static关键字。

  • 只能是可修改变量,不能是final变量,因为final的语义就是不可修改。实际上final的语义和volatile是有冲突的,这两个关键字不能同时存在。

  • 字段必须是volatile修饰的,也就是数据本身是读一致的,即在线程之间共享变量时保证立即可见。

  • 字段的描述类型(修饰符public/protected/default/private)是与调用者与操作对象字段的关系一致。也就是说调用者能够直接操作对象字段,那么就可以反射进行原子操作。但是对于父类的字段,子类是不能直接操作的,尽管子类可以访问父类的字段。

2、AtomicLongFieldUpdater 主要方法

2.1 实例的创建

AtomicLongFieldUpdater 有一个 protected 的无参数构造方法,只能供子类使用。所以一般情况下创建一个 AtomicLongFieldUpdater 实例需要使用该类提供的一个静态方法 newUpdater。

AtomicLongFieldUpdater 可以为一个用于更新指定类的声明为volatile类型的属性进行原子性更新,通过调用 AtomicLongFieldUpdater 的静态方法 newUpdater 创建实例,接受三个参数:

  • 第一个参数:包含要更新属性/字段的类的类型,即需要更新字段所在的class类
  • 第二个参数:更新属性/字段的名称
public static void main(String[] args) {
    Student student = new Student();
    //创建 AtomicLongFieldUpdater 对象
    AtomicLongFieldUpdater<Student> fieldUpdater = AtomicLongFieldUpdater.newUpdater(Student.class, "id");
    Person person = new Person(12345678L);
    // 比较person的"id"属性,如果id的值为12345678L,则设置为1000。
    fieldUpdater.compareAndSet(person, 12345678L, 1000L);
    System.out.println("id="+person.getId());
}
			
//测试类   
public class Student {
    volatile long id;
    public Person(long id) {
        this.id = id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public long getId() {
        return id;
    }
}

该示例代码通过调用 AtomicLongFieldUpdater.newUpdater(Student.class, "id") 静态方法生成 Student 类的 Long 类型的 id 字段的原子修改器 updater,然后调用它的 compareAndSet 方法判断 student 对象的 id 值,如果比较相等就重新赋值 1000L。

2.2 主要方法

// 受保护的无操作构造方法,供子类使用。
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)

3、AtomicLongFieldUpdater 演示示例

3.1 演示示例1

class Number {
    public volatile long value;
}

public class AtomicLongFieldUpdaterTest {

    public static void main(String[] args) {

        AtomicLongFieldUpdater<Number> value = AtomicLongFieldUpdater.newUpdater(Number.class, "value");

        Number number = new Number();
        // 设置number对象的value字段值为1000
        value.set(number, 1000);
        // 获取number对象的value字段值
        System.out.println(value.get(number));
        // 对number对象的value加1,获取加1后的值
        System.out.println(value.incrementAndGet(number));

    }
}

在上述代码示例中,创建 AtomicLongFieldUpdater 对象的时候需要指定对象的类型和要更新类中的哪个字段,此处要更新的是 Number 类中的 value 字段。最终输出如下:

1000
1001

3.2 演示示例2

  1. 计票类:
public class Detail {
    public volatile long numberTimesInvoked;

    public int getNumberTimesInvoked() {
        return numberTimesInvoked;
    }

    public void setNumberTimesInvoked(long numberTimesInvoked) {
        this.numberTimesInvoked = numberTimesInvoked;
    }
}
  1. 辅助代码为了验证并发的情况:
public class AtomicNumber {
    public static int A=0;
}
  1. 编写测试计算类,模拟多线程环境操作 AtomicLongFieldUpdater:
import java.util.concurrent.atomic.AtomicLongFieldUpdater;

public class AtomicLongFieldUpdaterCounter {
    //构造计数对象
    private AtomicLongFieldUpdater<Detail> atomicLongFieldUpdaterUpdater = AtomicLongFieldUpdater.newUpdater(Detail.class,"numberTimesInvoked");

    public Integer addOne(Detail detail){
        return this.atomicLongFieldUpdaterUpdater.incrementAndGet(detail);
    }
    public Integer subOne(Detail detail){
        return this.atomicLongFieldUpdaterUpdater.decrementAndGet(detail);
    }

    public static void main(String[] args) throws InterruptedException {
        final Detail detail = new Detail();
        final AtomicLongFieldUpdaterCounter a = new AtomicLongFieldUpdaterCounter();
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100000; i++) {
                    AtomicNumber.A++;
                    a.addOne(detail);
                }
            }
        });
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100000; i++) {
                    AtomicNumber.A++;
                    a.subOne(detail);
                }
            }
        });
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(AtomicNumber.A);
        System.out.println(detail.getNumberTimesInvoked());
    }
}

代码运行结果:

197169
0

从结果可以看出:利用 AtomicLongFieldUpdater 可以保证对象属性不会发生并发访问的情况。

4、源码分析

AtomicLongFieldUpdater 的代码很简单,下面对 AtomicLongFieldUpdater 部分源码进行解析。

4.1 实现基础 - 构造方法

AtomicLongFieldUpdater 有一个 protected 的构造方法,只能供子类使用。所以一般情况下创建一个 AtomicLongFieldUpdater 实例需要使用该类提供的一个静态方法 newUpdater。

// 受保护的无操作构造方法,供子类使用。一般情况下都使用newUpdater创建对象。
protected AtomicLongFieldUpdater(){}

4.2 实现基础 - 创建实例的静态方法

创建实例的静态方法为 newUpdater 更新器,创建并返回一个用于更新包含给定字段的对象的更新器:

/**
 * 基于指定的 Class 类型和字段名称创建一个 AtomicLongFieldUpdater 实例,
 * 字段类型必须是 volatile long。
 */
@CallerSensitive
public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName){
    Class<?> caller = Reflection.getCallerClass();
    if(AtomicLong.VM_SUPPORT_LONG_CAS)
        return new CASUpdater<U> (tclass, fieldName, caller);
    else
        return new LockedUpdater<U>(tclass, fieldName, caller);
}

Class参数主要用于检查反射类型和泛型类型是否匹配。在进行方法调用的时候,T和U是一样的,都是目标类的类型。

  • tclass持有给定字段的目标对象的类类型。U是类类型对象tclass的类型。

  • fieldName是将要进行更新的字段名称

  • 如果字段不是被volatile修饰的long类型字段,会抛出IllegalArgumentException异常。

  • 如果目标类型中不包含这个字段,或者目标类型不匹配,或者目标字段基于Java语言的访问控制不允许访问,则会抛出反射异常,会在捕获之后抛出RuntimeException异常。

  • CallerSensitive注解,主要是配合Reflection.getCallerClass(),作用是避免自己写Reflection.getCallerClass()的参数,增加这个特性主要还是为了修复一个jdk中的利用双重反射的越权漏洞。

  • 在创建更新器的过程中,我们看到,会对虚拟机是否支持64位的cmpxchg指令进行判断,如果支持则创建基于CAS的原子性更新器,否则,就只能创建基于锁的更新器。

4.3 实现基础 - 主要方法

4.3.1 set方法

set 方法设置由此更新程序所管理的给定对象的字段。对于 compareAndSet 的后续调用,此操作可以确保充当可变存储。

public final void set(T obj, long newValue) {
    accessCheck(obj);
    U.putLongVolatile(obj, offset, newValue);
}

参数:

  • obj - 要设置其字段的对象
  • newValue - 新值

4.3.2 get方法

get 方法获取由给定对象在字段中保持的当前值。

public final long get(T obj) {
    accessCheck(obj);
    return U.getLongVolatile(obj, offset);
}

参数:

  • obj - 要获取其字段的对象

返回:

  • 当前值

4.3.3 lazySet方法

lazySet 方法最终将此更新程序管理的给定对象的字段设置为给定的更新值。

public final void lazySet(T obj, long newValue) {
    accessCheck(obj);
    U.putOrderedLong(obj, offset, newValue);
}

lazySet与set实现的功能类似,二者区别如下:

  • lazySet实现的是最终一致性,set实现的是强一致性
  • lazySet:多线程并发时,线程A调用unsafe.putOrderedInt更新newValue值时,只是把线程A内存中的元素更新成功了,但其它线程此时看不到线程A更新的newValue值,需过一会,线程A更新的newValue才会刷入到主内存中,此时其它线程才能看到线程A更新的值
  • set: 多线程并发时,线程A更新的值会立即刷入主内存中
  • 总结:对于数据一致性要求高的建议用set

4.3.4 获取设置方法

getAndSet 方法为获取设置方法,即以原子方式将此更新程序管理的给定对象的字段设置为给定值并返回旧值。

public final long getAndSet(T obj, long newValue) {
    accessCheck(obj);
    return U.getAndSetLong(obj, offset, newValue);
}

参数:

  • obj - 要获取并设置其字段的对象
  • newValue - 新值

返回:

  • 以前的值

4.3.5 比较设置方法

比较设置方法有 compareAndSet 和 weakCompareAndSet。

compareAndSet:如果对象的给定字段的当前值等于期望值(即, expect参数的值),我们就把对象的给定字段的值原子地设置为给定的更新值(即,update参数的值)。这个方法只对compareAndSet和set的方法调用提供原子性保证,但是对于这个字段的其他修改,不提供原子性的保证。

如果obj对象不是构造方法里的对象给出的类型的实例,那么,会抛出ClassCastException异常。

weakCompareAndSet方法与compareAndSet方法基本相同,唯一的区别是这个方法可能由于错误而失败,并且不提供顺序保证,因此很少用作compareAndSet的替换方法。

public final boolean compareAndSet(T obj, long expect, long update) {
    accessCheck(obj);
    return U.compareAndSwapLong(obj, offset, expect, update);
}

public final boolean weakCompareAndSet(T obj, long expect, long update) {
    accessCheck(obj);
    return U.compareAndSwapLong(obj, offset, expect, update);
}

参数:

  • obj - 有条件地设置其字段的对象
  • expect - 预期值
  • update - 新值

返回:

  • 如果成功,则返回 true。

4.3.6 原子增加属性的值,并返回旧值

以原子方式将此更新器管理的给定对象的当前值 + N,并返回旧值。

public final long getAndAdd(T obj, long delta) {
    accessCheck(obj);
    return U.getAndAddLong(obj, offset, delta);
}

4.3.7 原子减少属性的值,并返回旧值

以原子方式将此更新器管理的给定对象的当前值 - 1,并返回旧值。

//-1然后返回原来的元素,实际调用的是getAndAdd
public final int getAndDecrement(T obj) {
    return getAndAdd(obj, -1);
}

4.3.8 原子更新属性的值,并返回旧值

以原子方式使用给定的方法获取的值更新当前的值,并返回旧值,自JDK1.8起提供。LongUnaryOperator会被多次调用

/**
 * 以原子方式使用给定的方法获取的值更新当前的值,并返回旧值,自JDK1.8起提供。LongUnaryOperator会被多次调用
 */

public final long getAndUpdate(T obj, LongUnaryOperator updateFunction) {
    long prev, next;
    do {
       prev = get(obj);
       next = updateFunction.applyAsLong(prev);
    } while (!compareAndSet(obj, prev, next));
    return prev;
}

以原子方式使用给定的方法获取的值将x作为参数更新当前的值,并返回旧值,自JDK1.8起提供。LongUnaryOperator会被多次调用

/**
 * 以原子方式使用给定的方法获取的值将x作为参数更新当前的值,并返回旧值,自JDK1.8起提供。LongUnaryOperator会被多次调用
 */
public final long getAndAccumulate(T obj, long x,
                        LongBinaryOperator accumulatorFunction) {
    long prev, next;
    do {
        prev = get(obj);
        next = accumulatorFunction.applyAsLong(prev, x);
    } while (!compareAndSet(obj, prev, next));
    return prev;
}

4.3.9 原子增加属性的值,并返回新值

以原子方式将此更新器管理的给定对象的当前值 + 1/N,并返回新值。

// 以原子方式将此更新器管理的给定对象字段当前值加1
public long incrementAndGet(T obj) {
   long prev, next;
   do {
       prev = get(obj);
       next = prev + 1;
   } while (!compareAndSet(obj, prev, next));
   return next;
}

//以原子方式将给定值添加到此更新器管理的给定对象的字段的当前值
public long addAndGet(T obj, long delta) {
   long prev, next;
   do {
      prev = get(obj);
      next = prev + delta;
   } while (!compareAndSet(obj, prev, next));
   return next;
}

4.3.10 原子减少属性的值,并返回新值

以原子方式将此更新器管理的给定对象的当前值 - 1,并返回新值。

// 以原子方式将此更新器管理的给定对象字段当前值减1
public long decrementAndGet(T obj) {
    long prev, next;
    do {
       prev = get(obj);
       next = prev - 1;
    } while (!compareAndSet(obj, prev, next));
    return next;
}

4.3.11 原子更新属性的值,并返回新值

以原子方式使用给定的方法获取的值更新当前的值,并返回新值,自JDK1.8起提供。LongUnaryOperator会被多次调用

// 以原子方式使用给定的方法获取的值更新当前的值,并返回新值,自JDK1.8起提供。LongUnaryOperator会被多次调用
public final long updateAndGet(T obj, LongUnaryOperator updateFunction) {
    long prev, next;
    do {
       prev = get(obj);
       next = updateFunction.applyAsLong(prev);
    } while (!compareAndSet(obj, prev, next));
    return next;
}

以原子方式使用给定的方法获取的值将x作为参数更新当前的值,并返回旧值,自JDK1.8起提供。LongUnaryOperator会被多次调用

// 以原子方式使用给定的方法获取的值将x作为参数更新当前的值,并返回旧值,自JDK1.8起提供。LongUnaryOperator会被多次调用
public final long accumulateAndGet(T obj, long x,
                                   LongBinaryOperator accumulatorFunction) {
    long prev, next;
    do {
       prev = get(obj);
       next = accumulatorFunction.applyAsLong(prev, x);
    } while (!compareAndSet(obj, prev, next));
    return next;
}

5、AtomicLongFieldUpdater完整源码

AtomicLongFieldUpdater完整源码如下(基于JDK 1.8.0_101):

package java.util.concurrent.atomic;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Objects;
import java.util.function.LongBinaryOperator;
import java.util.function.LongUnaryOperator;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;

public abstract class AtomicLongFieldUpdater<T> {
    // 针对某个类的某个字段创建一个updater更新器,会对传入的类和字段使用反射检查类型是否匹配
    @CallerSensitive
    public static <U> java.util.concurrent.atomic.AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
        Class<?> caller = Reflection.getCallerClass();
        if (AtomicLong.VM_SUPPORTS_LONG_CAS)
            return new java.util.concurrent.atomic.AtomicLongFieldUpdater.CASUpdater<U>(tclass, fieldName, caller);
        else
            return new java.util.concurrent.atomic.AtomicLongFieldUpdater.LockedUpdater<U>(tclass, fieldName, caller);
    }

    // 保护构造方法
    protected AtomicLongFieldUpdater() {
    }

    // 如果当前值等于预期值,则以原子方式将此更新器所管理的给定对象的字段设置为给定的更新值
    public abstract boolean compareAndSet(T obj, long expect, long update);

    //
    public abstract boolean weakCompareAndSet(T obj, long expect, long update);

    // 将此更新器管理的给定对象的字段设置为给定更新值
    public abstract void set(T obj, long newValue);

    //
    public abstract void lazySet(T obj, long newValue);

    // 获取此更新器管理的在给定对象的字段中保持的当前值
    public abstract long get(T obj);

    // 将此更新器管理的给定对象的字段以原子方式设置为给定值,并返回旧值
    public long getAndSet(T obj, long newValue) {
        long prev;
        do {
            prev = get(obj);
        } while (!compareAndSet(obj, prev, newValue));
        return prev;
    }

    // 以原子方式将此更新器管理的给定对象字段的当前值加1
    public long getAndIncrement(T obj) {
        long prev, next;
        do {
            prev = get(obj);
            next = prev + 1;
        } while (!compareAndSet(obj, prev, next));
        return prev;
    }

    // 以原子方式将此更新器管理的给定对象字段当前值减1
    public long getAndDecrement(T obj) {
        long prev, next;
        do {
            prev = get(obj);
            next = prev - 1;
        } while (!compareAndSet(obj, prev, next));
        return prev;
    }

    // 以原子方式将给定值添加到此更新器管理的给定对象的字段的当前值
    public long getAndAdd(T obj, long delta) {
        long prev, next;
        do {
            prev = get(obj);
            next = prev + delta;
        } while (!compareAndSet(obj, prev, next));
        return prev;
    }

    // 以原子方式将此更新器管理的给定对象字段当前值加1
    public long incrementAndGet(T obj) {
        long prev, next;
        do {
            prev = get(obj);
            next = prev + 1;
        } while (!compareAndSet(obj, prev, next));
        return next;
    }

    // 以原子方式将此更新器管理的给定对象字段当前值减1
    public long decrementAndGet(T obj) {
        long prev, next;
        do {
            prev = get(obj);
            next = prev - 1;
        } while (!compareAndSet(obj, prev, next));
        return next;
    }

    // 以原子方式将给定值添加到此更新器管理的给定对象的字段的当前值
    public long addAndGet(T obj, long delta) {
        long prev, next;
        do {
            prev = get(obj);
            next = prev + delta;
        } while (!compareAndSet(obj, prev, next));
        return next;
    }

    // 以原子方式使用给定的方法获取的值更新当前的值,并返回旧值,自JDK1.8起提供。LongUnaryOperator会被多次调用
    public final long getAndUpdate(T obj, LongUnaryOperator updateFunction) {
        long prev, next;
        do {
            prev = get(obj);
            next = updateFunction.applyAsLong(prev);
        } while (!compareAndSet(obj, prev, next));
        return prev;
    }

    // 以原子方式使用给定的方法获取的值更新当前的值,并返回新值,自JDK1.8起提供。LongUnaryOperator会被多次调用
    public final long updateAndGet(T obj, LongUnaryOperator updateFunction) {
        long prev, next;
        do {
            prev = get(obj);
            next = updateFunction.applyAsLong(prev);
        } while (!compareAndSet(obj, prev, next));
        return next;
    }

    // 以原子方式使用给定的方法获取的值将x作为参数更新当前的值,并返回旧值,自JDK1.8起提供。LongUnaryOperator会被多次调用
    public final long getAndAccumulate(T obj, long x,
                                       LongBinaryOperator accumulatorFunction) {
        long prev, next;
        do {
            prev = get(obj);
            next = accumulatorFunction.applyAsLong(prev, x);
        } while (!compareAndSet(obj, prev, next));
        return prev;
    }

    // 以原子方式使用给定的方法获取的值将x作为参数更新当前的值,并返回旧值,自JDK1.8起提供。LongUnaryOperator会被多次调用
    public final long accumulateAndGet(T obj, long x,
                                       LongBinaryOperator accumulatorFunction) {
        long prev, next;
        do {
            prev = get(obj);
            next = accumulatorFunction.applyAsLong(prev, x);
        } while (!compareAndSet(obj, prev, next));
        return next;
    }

    // CAS原子更新器
    private static final class CASUpdater<T> extends java.util.concurrent.atomic.AtomicLongFieldUpdater<T> {
        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
        private final long offset;
        /**
         * if field is protected, the subclass constructing updater, else
         * the same as tclass
         */
        private final Class<?> cclass;
        /**
         * class holding the field
         */
        private final Class<T> tclass;

        CASUpdater(final Class<T> tclass, final String fieldName,
                   final Class<?> caller) {
            final Field field;
            final int modifiers;
            try {
                // 禁止对字段的安全检查
                field = AccessController.doPrivileged(
                        new PrivilegedExceptionAction<Field>() {
                            public Field run() throws NoSuchFieldException {
                                return tclass.getDeclaredField(fieldName);
                            }
                        });
                // 获取字段的修饰符
                modifiers = field.getModifiers();
                // 检查访问权限
                sun.reflect.misc.ReflectUtil.ensureMemberAccess(
                        caller, tclass, null, modifiers);
                ClassLoader cl = tclass.getClassLoader();
                ClassLoader ccl = caller.getClassLoader();
                if ((ccl != null) && (ccl != cl) &&
                        ((cl == null) || !isAncestor(cl, ccl))) {
                    sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
                }
            } catch (PrivilegedActionException pae) {
                throw new RuntimeException(pae.getException());
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }

            // 检查字段类型是否为long
            if (field.getType() != long.class)
                throw new IllegalArgumentException("Must be long type");

            // 检查是否被volatile修饰
            if (!Modifier.isVolatile(modifiers))
                throw new IllegalArgumentException("Must be volatile type");

            // Access to protected field members is restricted to receivers only
            // of the accessing class, or one of its subclasses, and the
            // accessing class must in turn be a subclass (or package sibling)
            // of the protected member's defining class.
            // If the updater refers to a protected field of a declaring class
            // outside the current package, the receiver argument will be
            // narrowed to the type of the accessing class.
            this.cclass = (Modifier.isProtected(modifiers) &&
                    tclass.isAssignableFrom(caller) &&
                    !isSamePackage(tclass, caller))
                    ? caller : tclass;
            this.tclass = tclass;
            this.offset = U.objectFieldOffset(field);
        }

        /**
         * Checks that target argument is instance of cclass.  On
         * failure, throws cause.
         */
        private final void accessCheck(T obj) {
            if (!cclass.isInstance(obj))
                throwAccessCheckException(obj);
        }

        /**
         * Throws access exception if accessCheck failed due to
         * protected access, else ClassCastException.
         */
        private final void throwAccessCheckException(T obj) {
            if (cclass == tclass)
                throw new ClassCastException();
            else
                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()));
        }

        public final boolean compareAndSet(T obj, long expect, long update) {
            accessCheck(obj);
            return U.compareAndSwapLong(obj, offset, expect, update);
        }

        public final boolean weakCompareAndSet(T obj, long expect, long update) {
            accessCheck(obj);
            return U.compareAndSwapLong(obj, offset, expect, update);
        }

        public final void set(T obj, long newValue) {
            accessCheck(obj);
            U.putLongVolatile(obj, offset, newValue);
        }

        public final void lazySet(T obj, long newValue) {
            accessCheck(obj);
            U.putOrderedLong(obj, offset, newValue);
        }

        public final long get(T obj) {
            accessCheck(obj);
            return U.getLongVolatile(obj, offset);
        }

        public final long getAndSet(T obj, long newValue) {
            accessCheck(obj);
            return U.getAndSetLong(obj, offset, newValue);
        }

        public final long getAndAdd(T obj, long delta) {
            accessCheck(obj);
            return U.getAndAddLong(obj, offset, delta);
        }

        public final long getAndIncrement(T obj) {
            return getAndAdd(obj, 1);
        }

        public final long getAndDecrement(T obj) {
            return getAndAdd(obj, -1);
        }

        public final long incrementAndGet(T obj) {
            return getAndAdd(obj, 1) + 1;
        }

        public final long decrementAndGet(T obj) {
            return getAndAdd(obj, -1) - 1;
        }

        public final long addAndGet(T obj, long delta) {
            return getAndAdd(obj, delta) + delta;
        }
    }

    private static final class LockedUpdater<T> extends java.util.concurrent.atomic.AtomicLongFieldUpdater<T> {
        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
        private final long offset;
        /**
         * if field is protected, the subclass constructing updater, else
         * the same as tclass
         */
        private final Class<?> cclass;
        /**
         * class holding the field
         */
        private final Class<T> tclass;

        LockedUpdater(final Class<T> tclass, final String fieldName,
                      final Class<?> caller) {
            Field field = null;
            int modifiers = 0;
            try {
                field = AccessController.doPrivileged(
                        new PrivilegedExceptionAction<Field>() {
                            public Field run() throws NoSuchFieldException {
                                return tclass.getDeclaredField(fieldName);
                            }
                        });
                modifiers = field.getModifiers();
                sun.reflect.misc.ReflectUtil.ensureMemberAccess(
                        caller, tclass, null, modifiers);
                ClassLoader cl = tclass.getClassLoader();
                ClassLoader ccl = caller.getClassLoader();
                if ((ccl != null) && (ccl != cl) &&
                        ((cl == null) || !isAncestor(cl, ccl))) {
                    sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
                }
            } catch (PrivilegedActionException pae) {
                throw new RuntimeException(pae.getException());
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }

            if (field.getType() != long.class)
                throw new IllegalArgumentException("Must be long type");

            if (!Modifier.isVolatile(modifiers))
                throw new IllegalArgumentException("Must be volatile type");

            // Access to protected field members is restricted to receivers only
            // of the accessing class, or one of its subclasses, and the
            // accessing class must in turn be a subclass (or package sibling)
            // of the protected member's defining class.
            // If the updater refers to a protected field of a declaring class
            // outside the current package, the receiver argument will be
            // narrowed to the type of the accessing class.
            this.cclass = (Modifier.isProtected(modifiers) &&
                    tclass.isAssignableFrom(caller) &&
                    !isSamePackage(tclass, caller))
                    ? caller : tclass;
            this.tclass = tclass;
            this.offset = U.objectFieldOffset(field);
        }

        /**
         * Checks that target argument is instance of cclass.  On
         * failure, throws cause.
         */
        private final void accessCheck(T obj) {
            if (!cclass.isInstance(obj))
                throw accessCheckException(obj);
        }

        /**
         * Returns access exception if accessCheck failed due to
         * protected access, else ClassCastException.
         */
        private final RuntimeException accessCheckException(T obj) {
            if (cclass == tclass)
                return new ClassCastException();
            else
                return new RuntimeException(
                        new IllegalAccessException(
                                "Class " +
                                        cclass.getName() +
                                        " can not access a protected member of class " +
                                        tclass.getName() +
                                        " using an instance of " +
                                        obj.getClass().getName()));
        }

        public final boolean compareAndSet(T obj, long expect, long update) {
            accessCheck(obj);
            synchronized (this) {
                long v = U.getLong(obj, offset);
                if (v != expect)
                    return false;
                U.putLong(obj, offset, update);
                return true;
            }
        }

        public final boolean weakCompareAndSet(T obj, long expect, long update) {
            return compareAndSet(obj, expect, update);
        }

        public final void set(T obj, long newValue) {
            accessCheck(obj);
            synchronized (this) {
                U.putLong(obj, offset, newValue);
            }
        }

        public final void lazySet(T obj, long newValue) {
            set(obj, newValue);
        }

        public final long get(T obj) {
            accessCheck(obj);
            synchronized (this) {
                return U.getLong(obj, offset);
            }
        }
    }

    // 判断ClassLoader继承性
    static boolean isAncestor(ClassLoader first, ClassLoader second) {
        ClassLoader acl = first;
        do {
            acl = acl.getParent();
            if (second == acl) {
                return true;
            }
        } while (acl != null);
        return false;
    }

    // 判断两个类是否在同一个包内
    private static boolean isSamePackage(Class<?> class1, Class<?> class2) {
        return class1.getClassLoader() == class2.getClassLoader()
                && Objects.equals(getPackageName(class1), getPackageName(class2));
    }

    // 获取包名
    private static String getPackageName(Class<?> cls) {
        String cn = cls.getName();
        int dot = cn.lastIndexOf('.');
        return (dot != -1) ? cn.substring(0, dot) : "";
    }
}
0

评论区