Java并发编程札记-(三)JUC原子类-05原子方式更新类的指定volatile字段

AtomicReferenceFieldUpdater、AtomicIntegerFieldUpdater和AtomicLongFieldUpdater是基于反射的实用工具,可以提供对关联字段类型的访问。例如AtomicLongFieldUpdater可以对指定类的指定volatile long字段进行原子更新。本文以AtomicLongFieldUpdater为例来学习。

API

//构造方法摘要
protected   AtomicLongFieldUpdater() 
          //受保护的无操作构造方法,供子类使用。

//方法摘要
 long   addAndGet(T obj, long delta) 
          //以原子方式将给定值添加到此更新器管理的给定对象的字段的当前值。
 abstract  boolean  compareAndSet(T obj, long expect, long update) 
          //如果当前值 == 预期值,则以原子方式将此更新器所管理的给定对象的字段设置为给定的更新值。
 long   decrementAndGet(T obj) 
          //以原子方式将此更新器管理的给定对象字段当前值减 1。
 abstract  long get(T obj) 
          //获取此更新器管理的在给定对象的字段中保持的当前值。
 long   getAndAdd(T obj, long delta) 
          //以原子方式将给定值添加到此更新器管理的给定对象的字段的当前值。
 long   getAndDecrement(T obj) 
          //以原子方式将此更新器管理的给定对象字段当前值减 1。
 long   getAndIncrement(T obj) 
          //以原子方式将此更新器管理的给定对象字段的当前值加 1。
 long   getAndSet(T obj, long newValue) 
          //将此更新器管理的给定对象的字段以原子方式设置为给定值,并返回旧值。
 long   incrementAndGet(T obj) 
          //以原子方式将此更新器管理的给定对象字段当前值加 1。
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) 
          //如果当前值 == 预期值,则以原子方式将此更新器所管理的给定对象的字段设置为给定的更新值。
//以下是JDK1.8新增的部分
long    getAndUpdate(int i, LongUnaryOperator updateFunction)
         //将当前值以原子方式更新为updateFunction方法的结果,并返回更新前的值
long updateAndGet(int i, LongUnaryOperator updateFunction)
         //将当前值以原子方式更新为updateFunction方法的结果,并返回更新后的值
long getAndAccumulate(int i, long x, LongBinaryOperator accumulatorFunction)
         //将当前值以原子方式更新为updateFunction方法的结果(方法参数为x和当前值),并返回更新前的值
long accumulateAndGet(int i, long x, LongBinaryOperator accumulatorFunction)
         //将当前值以原子方式更新为updateFunction方法的结果(方法参数为x和当前值),并返回更新后的值

例1:AtomicLongFieldUpdater原子方式更新类的指定volatile字段

:通常情况下,在Java中的++i或者-–i不是线程安全的。一般情况下,只能加锁才能保证上述操作的原子性。有了AtomicLongFieldUpdater后,使用AtomicLongFieldUpdater就可以保证上述操作的原子性。

Counter是一个计数器类。

class Counter extends Thread {
    private static long counter = 0;

    public static long addOne() {
        return ++counter;
    }
}

在多线程环境下测试其是否可用。

public class CounterTest {
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            Thread thread = new Thread() {
                public void run() {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (Counter.addOne() == 100) {
                        System.out.println("计数器值最终值为100");
                    }
                }
            };
            thread.start();
        }
    }
}

测试程序,在连续运行100次++counter后,判断计数器值是否为100,如果为100就打印计数器值最终值为100,否则就什么都不打印。
数次运行程序后,发现大多数结果是什么都没有打印,说明次计数器在多线程环境下不可用。
修改计数器类。

class Counter {
    private volatile long counter = 0;

    static AtomicLongFieldUpdater updater = AtomicLongFieldUpdater.newUpdater(Counter.class, "counter");
    static Counter safeCounter = new Counter ();

    public static long addOne() {
        return updater.addAndGet(safeCounter, 1);
    }
}

在多线程环境下测试其是否可用。数次运行程序后,发现结果全部为计数器值最终值为100。

实现原理

与其他原子类一样,AtomicLongFieldUpdater也是基于CAS实现的。

AtomicReferenceFieldUpdater、AtomicIntegerFieldUpdater与AtomicLongFieldUpdater很相似,就不多做介绍了。

本文就讲到这里,想了解Java并发编程更多内容请参考:

  • Java并发编程札记-目录

END.

    原文作者:java并发
    原文地址: http://blog.csdn.net/panweiwei1994/article/details/78737833
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞