zoukankan      html  css  js  c++  java
  • Java多线程系列--“JUC原子类”04之 AtomicReference原子类

     

    概要

    本章对AtomicReference引用类型的原子类进行介绍。内容包括:
    AtomicReference介绍和函数列表
    AtomicReference源码分析(基于JDK1.7.0_40)
    AtomicReference示例

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3514623.html

    AtomicReference介绍和函数列表

    AtomicReference是作用是对"对象"进行原子操作。

    AtomicReference函数列表

    // 使用 null 初始值创建新的 AtomicReference。
    AtomicReference()
    // 使用给定的初始值创建新的 AtomicReference。
    AtomicReference(V initialValue)
    
    // 如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值。
    boolean compareAndSet(V expect, V update)
    // 获取当前值。
    V get()
    // 以原子方式设置为给定值,并返回旧值。
    V getAndSet(V newValue)
    // 最终设置为给定值。
    void lazySet(V newValue)
    // 设置为给定值。
    void set(V newValue)
    // 返回当前值的字符串表示形式。
    String toString()
    // 如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值。
    boolean weakCompareAndSet(V expect, V update)

    AtomicReference源码分析(基于JDK1.7.0_40)

    在JDK1.7.0_40中AtomicReference.java的源码如下:

    public class AtomicReference<V>  implements java.io.Serializable {
        private static final long serialVersionUID = -1848883965231344442L;
    
        // 获取Unsafe对象,Unsafe的作用是提供CAS操作
        private static final Unsafe unsafe = Unsafe.getUnsafe();
        private static final long valueOffset;
    
        static {
          try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicReference.class.getDeclaredField("value"));
          } catch (Exception ex) { throw new Error(ex); }
        }
    
        // volatile类型
        private volatile V value;
    
        public AtomicReference(V initialValue) {
            value = initialValue;
        }
    
        public AtomicReference() {
        }
    
        public final V get() {
            return value;
        }
    
        public final void set(V newValue) {
            value = newValue;
        }
    
        public final void lazySet(V newValue) {
            unsafe.putOrderedObject(this, valueOffset, newValue);
        }
    
        public final boolean compareAndSet(V expect, V update) {
            return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
        }
    
        public final boolean weakCompareAndSet(V expect, V update) {
            return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
        }
    
        public final V getAndSet(V newValue) {
            while (true) {
                V x = get();
                if (compareAndSet(x, newValue))
                    return x;
            }
        }
    
        public String toString() {
            return String.valueOf(get());
        }
    }

    说明
    AtomicReference的源码比较简单。它是通过"volatile"和"Unsafe提供的CAS函数实现"原子操作。
    (01) value是volatile类型。这保证了:当某线程修改value的值时,其他线程看到的value值都是最新的value值,即修改之后的volatile的值。
    (02) 通过CAS设置value。这保证了:当某线程池通过CAS函数(如compareAndSet函数)设置value时,它的操作是原子的,即线程在操作value时不会被中断。

     

    AtomicReference示例

    // AtomicReferenceTest.java的源码
    import java.util.concurrent.atomic.AtomicReference;
    
    public class AtomicReferenceTest {
        
        public static void main(String[] args){
    
            // 创建两个Person对象,它们的id分别是101和102。
            Person p1 = new Person(101);
            Person p2 = new Person(102);
            // 新建AtomicReference对象,初始化它的值为p1对象
            AtomicReference ar = new AtomicReference(p1);
            // 通过CAS设置ar。如果ar的值为p1的话,则将其设置为p2。
            ar.compareAndSet(p1, p2);
    
            Person p3 = (Person)ar.get();
            System.out.println("p3 is "+p3);
            System.out.println("p3.equals(p1)="+p3.equals(p1));
        }
    }
    
    class Person {
        volatile long id;
        public Person(long id) {
            this.id = id;
        }
        public String toString() {
            return "id:"+id;
        }
    }

    运行结果

    p3 is id:102
    p3.equals(p1)=false

    结果说明
    新建AtomicReference对象ar时,将它初始化为p1。
    紧接着,通过CAS函数对它进行设置。如果ar的值为p1的话,则将其设置为p2。
    最后,获取ar对应的对象,并打印结果。p3.equals(p1)的结果为false,这是因为Person并没有覆盖equals()方法,而是采用继承自Object.java的equals()方法;而Object.java中的equals()实际上是调用"=="去比较两个对象,即比较两个对象的地址是否相等。


    更多内容

    1. Java多线程系列--“JUC原子类”01之 框架

    2. Java多线程系列--“JUC原子类”02之 AtomicLong原子类

    3. Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类

    4. Java多线程系列目录(共xx篇)

  • 相关阅读:
    解释机器学习模型的一些方法(一)——数据可视化
    机器学习模型解释工具-Lime
    Hive SQL 语法学习与实践
    LeetCode 198. 打家劫舍(House Robber)LeetCode 213. 打家劫舍 II(House Robber II)
    LeetCode 148. 排序链表(Sort List)
    LeetCode 18. 四数之和(4Sum)
    LeetCode 12. 整数转罗马数字(Integer to Roman)
    LeetCode 31. 下一个排列(Next Permutation)
    LeetCode 168. Excel表列名称(Excel Sheet Column Title)
    论FPGA建模,与面向对象编程的相似性
  • 原文地址:https://www.cnblogs.com/skywang12345/p/3514623.html
Copyright © 2011-2022 走看看