原子引用AtomicReference

除了基本类型有原子封装类外,任意引用类型也可以通过原子引用进行原子操作

该类的方法有:

  • get

public final V get()

获取当前值。

  • 结果

当前值

  • set

public final void set(V newValue)

设置为给定值。

  • 参数

newValue - 新价值

  • lazySet

public final void lazySet(V newValue)

最终设定为给定值。

  • 参数

newValue - 新价值

  • 从以下版本开始:

1.6

  • compareAndSet

public final boolean compareAndSet(V expect,
                                  V update)

如果当前值 ==为预期值,则将值设置为给定的更新值。

  • 参数

expect - 预期值

update - 新的价值

  • 结果

true如果成功。 False return表示实际值不等于预期值。

  • weakCompareAndSet

public final boolean weakCompareAndSet(V expect,
                                      V update)

如果当前值为==的预期值,则将该值原子设置为给定的更新值。

May fail spuriously and does not provide ordering guarantees ,所以只是很少适合替代compareAndSet

  • 参数

expect - 预期值

update - 新的价值

  • 结果

true如果成功

  • getAndSet

public final V getAndSet(V newValue)

将原子设置为给定值并返回旧值。

  • 参数

newValue - 新值

  • 结果

以前的值

  • updateAndGet

public final V updateAndGet(UnaryOperator updateFunction)

使用给定函数的结果原子更新当前值,返回更新的值。 该功能应该是无副作用的,因为尝试的更新由于线程之间的争用而失败时可能会被重新应用。

  • 参数

updateFunction - 无副作用的功能

  • 结果

更新的值

  • 从以下版本开始:

1.8

  • getAndAccumulate

public final V getAndAccumulate(V x,
                               BinaryOperator accumulatorFunction)

使用给定函数应用给当前值和给定值的结果原子更新当前值,返回上一个值。 该功能应该是无副作用的,因为尝试的更新由于线程之间的争用而失败时可能会被重新应用。 该函数应用当前值作为其第一个参数,给定的更新作为第二个参数。

  • 参数

x - 更新值

accumulatorFunction - 两个参数的无副作用的函数

  • 结果

以前的值

  • 从以下版本开始:

1.8

  • accumulateAndGet

public final V accumulateAndGet(V x,
                               BinaryOperator accumulatorFunction)

使用将给定函数应用于当前值和给定值的结果原子更新当前值,返回更新后的值。 该功能应该是无副作用的,因为尝试的更新由于线程之间的争用而失败时可能会被重新应用。 该函数应用当前值作为其第一个参数,给定的更新作为第二个参数。

  • 参数

x - 更新值

accumulatorFunction - 两个参数的无副作用函数

  • 结果

更新的值

  • 从以下版本开始:

1.8

拓展

  • ABA 问题的解决

    • ABA Demo
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.atomic.AtomicReference;
    
    public class ABADemo {
       static AtomicReference atomicInt = new AtomicReference<>(100);
    
       public static void main(String[] args) {
           new Thread(() -> {
               atomicInt.compareAndSet(100, 101);
               atomicInt.compareAndSet(101, 100);
           }, "t1").start();
    
           new Thread(() -> {
               try {
                   TimeUnit.SECONDS.sleep(1);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               System.out.println(atomicInt.compareAndSet(100, 111) + " " + atomicInt.get());
           }, "t2").start();
       }
    
    
    }
    
    
    • 使用AtomicStampReference解决问题
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.atomic.AtomicStampedReference;
    
    public class ABADemo {
       static AtomicStampedReference atomicInt = new AtomicStampedReference<>(100, 1);
    
       public static void main(String[] args) {
           new Thread(() -> {
               atomicInt.compareAndSet(100, 101, atomicInt.getStamp(), atomicInt.getStamp()+1);
               atomicInt.compareAndSet(101, 100, atomicInt.getStamp(), atomicInt.getStamp()+1);
           }, "t1").start();
    
           new Thread(() -> {
               int stamp = atomicInt.getReference();
               try {
                   TimeUnit.SECONDS.sleep(1);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               System.out.println(atomicInt.compareAndSet(100, 111, stamp, stamp+1) + " " + atomicInt.getReference() + " 当前版本" + atomicInt.getStamp());
           }, "t2").start();
       }
    }
    
    

    思考:AtomicStampedReference 相比较 AtomicReference 相当于“故技重施”,把CAS机制再次使用,加了一个Stamp变量

你可能感兴趣的:(原子引用AtomicReference)