面试:AtomicReference与AtomicReferenceFieldUpdater

330 阅读1分钟

思考:

需要回答用法与区别,最好有实例

AtomicReference用法

static class Hold {
        AtomicReference<String> value = new AtomicReference<>();
    }
    
    //AtomicReference
        Hold hold = new Hold();
        hold.value.set("123");
        hold.value.compareAndSet("123","456");
        String val = hold.value.getAndUpdate(new UnaryOperator<String>() {
            @Override
            public String apply(String s) {
                return "1233454";
            }
        });
        System.out.println(val+"-"+hold.value.get());

AtomicReferenceFieldUpdater

static class Hold2{
       public static AtomicReferenceFieldUpdater<Hold2,String> valueUpdate = AtomicReferenceFieldUpdater.newUpdater(Hold2.class,String.class,"val");
       volatile String val = "val";
    }
    
 //AtomicReferenceFieldUpdater
        Hold2 hold2 = new Hold2();
        Hold2.valueUpdate.set(hold2,"123");
        Hold2.valueUpdate.compareAndSet(hold2,"123","456");
        String val = Hold2.valueUpdate.getAndUpdate(hold2, new UnaryOperator<String>() {
            @Override
            public String apply(String s) {
                return "1233454";
            }
        });
        System.out.println(val+"-"+Hold2.valueUpdate.get(hold2));

相同点和不同点

  • 相同点 核心原子操作的原理基本一致,都是通过unsafe的CAS来实现,api使用也大同小异。
  • 不同点 AtomicReference:使用更加直接,但是不宜大量创建,会有内存问题。 AtomicReferenceFieldUpdater:基于反射来使用,使用时静态变量形式出现,不会有AtomicReference的内存问题,大量框架和系统api中都有使用到。比如BufferedInputSteam,其内存更新byte[] 需要保证原子性。