美文网首页
Java引用类型原子操作类 AtomicReference的用法

Java引用类型原子操作类 AtomicReference的用法

作者: 咕噜咕噜_f443 | 来源:发表于2020-03-19 22:51 被阅读0次

    /**

    * 类说明:演示引用类型的原子操作类

    */

    public class UseAtomicReference {

    static AtomicReference<UserInfo> atomicUserRef;

    public static void main(String[] args) {

    UserInfo user =new UserInfo("Mark",15);//要修改的实体的实例

    atomicUserRef =new AtomicReference(user);

    UserInfo updateUser =new UserInfo("Bill",17);

    boolean a =atomicUserRef.compareAndSet(user, updateUser);

    System.out.println(a);

    System.out.println(atomicUserRef.get());

    System.out.println(user);

    }

    //定义一个实体类

    static class UserInfo {

    private volatile Stringname;

    private int age;

    public UserInfo(String name,int age) {

    this.name = name;

    this.age = age;

    }

    public String getName() {

    return name;

    }

    public int getAge() {

    return age;

    }

    @Override

    public String toString() {

    return "UserInfo{" +

    "name='" +name +'\'' +

    ", age=" +age +

    '}';

    }

    }

    }

    注:

    atomicUserRef.compareAndSet(user, updateUser); 是改变了原有对象的引用路径,但本身的值并不会改变

    new AtomicReference(user);  将对象进行封装,使之变为原子操作

    AtomicStampedReference

    创建

    AtomicStampedReference<String> asr=new AtomicStampedReference("djy",0);

    源码为:

    注:

    这里可以看出AtomicStampedReference能够解决所谓的ABA问题,很简单版本号控制

    解决ABA问题

    /**

    * 类说明:演示带版本戳的原子操作类

    */

    public class UseAtomicStampedReference {

    static AtomicStampedReference<String>asr=new AtomicStampedReference("djy",0);

    public static void main(String[] args)throws InterruptedException {

    //拿到当前的版本号(旧)

    final int oldStamp =asr.getStamp();

    final String oldReference =asr.getReference();

    System.out.println(oldReference +"============" + oldStamp);

    Thread rightStampThread =new Thread(new Runnable() {

    @Override

                public void run() {

                    asr.compareAndSet(oldReference, "java", oldStamp, oldStamp + 1);

    }

            });

    Thread errorStampThread =new Thread(new Runnable() {

    @Override

                public void run() {

    String reference = asr.getReference();

                    int stamp = asr.getStamp();

                    asr.compareAndSet(reference, "C++", stamp, stamp + 1);

    }

            });

    rightStampThread.start();

    //让线程充分运行完毕

    rightStampThread.join();

    errorStampThread.start();

    errorStampThread.join();

    System.out.println(asr.getReference() +"============" +asr.getStamp());

    }

    }

    AtomicMarkableReference

    用法与AtomicStampedReference基本一致

    AtomicMarkableReference 与 AtomicStampedReference的区别?

    AtomicStampedReference

    构造方法中initialStamp(时间戳)用来唯一标识引用变量,在构造器内部,实例化了一个Pair对象,Pair对象记录了对象引用和时间戳信息,采用int作为时间戳,实际使用的时候,要保证时间戳唯一(一般做成自增的),如果时间戳如果重复,还会出现ABA的问题。

    AtomicStampedReference中的每一个引用变量都带上了pair.stamp这个时间戳,这样就可以解决CAS中的ABA的问题。

    /**

    * Creates a new {@code AtomicStampedReference} with the given

    * initial values.

    *

    * @param initialRef the initial reference

    * @param initialStamp the initial stamp

    */

    public AtomicStampedReference(V initialRef, int initialStamp) {

    pair = Pair.of(initialRef,initialStamp);

    }

    AtomicMarkableReference

    AtomicStampedReference可以知道,引用变量中途被更改了几次。有时候,我们并不关心引用变量更改了几次,只是单纯的关心是否更改过,所以就有了AtomicMarkableReference。

    AtomicMarkableReference的唯一区别就是不再用int标识引用,而是使用boolean变量——表示引用变量是否被更改过。

    构造函数

    /**

    * Creates a new {@code AtomicMarkableReference} with the given

    * initial values.

    *

    * @param initialRef the initial reference

    * @param initialMark the initial mark

    */

    public AtomicMarkableReference(V initialRef,boolean initialMark) {

    pair = Pair.of(initialRef, initialMark);

    }

    相关文章

      网友评论

          本文标题:Java引用类型原子操作类 AtomicReference的用法

          本文链接:https://www.haomeiwen.com/subject/luyryhtx.html