[多线程系列]Java 中atomic包的解析

前言:

  Java从JDK1.5开始提供了java.util.concurrent.atomic包,方便在多线程环境下进行原子操作。原子变量的底层使用了CPU提供的原子指令,但是不同的CPU架构可能提供的原子指令不一样,也有可能需要某种形式的内部锁,所以该方法不能绝对保证线程不被阻塞。

包介绍:

在atomic包里一共有12个类,四种原子更新方式,分别是原子更新基本类型,原子更新数组,原子更新引用和原子更新字段。Atomic包里的类基本都是使用Unsafe实现的包装类。

原子更新基本类型

  • AtomicInteger
  • AtomicLong
  • AtomicBoolean

原子更新引用

  • AtomicReference
  • AtomicMarkableReference
  • AtomicStampedReference 

原子更新数组

  • AtomicIntegerArray
  • AtomicLongArray
  • AtomicReferenceArray

原子更新字段

  • AtomicIntegerFieldUpdater
  • AtomicLongFieldUpdater
  • AtomicReferenceFieldUpdater

以下主要分析AtomicInteger,其他类大同小异

源码:

  

  1 /*
  2  * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  3  *
  4  *
  5  *
  6  *
  7  *
  8  *
  9  *
 10  *
 11  *
 12  *
 13  *
 14  *
 15  *
 16  *
 17  *
 18  *
 19  *
 20  *
 21  *
 22  *
 23  */
 24 
 25 /*
 26  *
 27  *
 28  *
 29  *
 30  *
 31  * Written by Doug Lea with assistance from members of JCP JSR-166
 32  * Expert Group and released to the public domain, as explained at
 33  * http://creativecommons.org/publicdomain/zero/1.0/
 34  */
 35 
 36 package java.util.concurrent.atomic;
 37 import sun.misc.Unsafe;
 38 
 39 /**
 40  * An {@code int} value that may be updated atomically.  See the
 41  * {@link java.util.concurrent.atomic} package specification for
 42  * description of the properties of atomic variables. An
 43  * {@code AtomicInteger} is used in applications such as atomically
 44  * incremented counters, and cannot be used as a replacement for an
 45  * {@link java.lang.Integer}. However, this class does extend
 46  * {@code Number} to allow uniform access by tools and utilities that
 47  * deal with numerically-based classes.
 48  *
 49  * @since 1.5
 50  * @author Doug Lea
 51 */
 52 public class AtomicInteger extends Number implements java.io.Serializable {
 53     private static final long serialVersionUID = 6214790243416807050L;
 54 
 55     // setup to use Unsafe.compareAndSwapInt for updates
 56     private static final Unsafe unsafe = Unsafe.getUnsafe();
 57     private static final long valueOffset;
 58 
 59     static {
 60       try {
 61         valueOffset = unsafe.objectFieldOffset
 62             (AtomicInteger.class.getDeclaredField("value"));
 63       } catch (Exception ex) { throw new Error(ex); }
 64     }
 65 
 66     private volatile int value;
 67 
 68     /**
 69      * Creates a new AtomicInteger with the given initial value.
 70      *
 71      * @param initialValue the initial value
 72      */
 73     public AtomicInteger(int initialValue) {
 74         value = initialValue;
 75     }
 76 
 77     /**
 78      * Creates a new AtomicInteger with initial value {@code 0}.
 79      */
 80     public AtomicInteger() {
 81     }
 82 
 83     /**
 84      * Gets the current value.
 85      *
 86      * @return the current value
 87      */
 88     public final int get() {
 89         return value;
 90     }
 91 
 92     /**
 93      * Sets to the given value.
 94      *
 95      * @param newValue the new value
 96      */
 97     public final void set(int newValue) {
 98         value = newValue;
 99     }
100 
101     /**
102      * Eventually sets to the given value.
103      *
104      * @param newValue the new value
105      * @since 1.6
106      */
107     public final void lazySet(int newValue) {
108         unsafe.putOrderedInt(this, valueOffset, newValue);
109     }
110 
111     /**
112      * Atomically sets to the given value and returns the old value.
113      *
114      * @param newValue the new value
115      * @return the previous value
116      */
117     public final int getAndSet(int newValue) {
118         for (;;) {
119             int current = get();
120             if (compareAndSet(current, newValue))
121                 return current;
122         }
123     }
124 
125     /**
126      * Atomically sets the value to the given updated value
127      * if the current value {@code ==} the expected value.
128      *
129      * @param expect the expected value
130      * @param update the new value
131      * @return true if successful. False return indicates that
132      * the actual value was not equal to the expected value.
133      */
134     public final boolean compareAndSet(int expect, int update) {
135         return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
136     }
137 
138     /**
139      * Atomically sets the value to the given updated value
140      * if the current value {@code ==} the expected value.
141      *
142      * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
143      * and does not provide ordering guarantees, so is only rarely an
144      * appropriate alternative to {@code compareAndSet}.
145      *
146      * @param expect the expected value
147      * @param update the new value
148      * @return true if successful.
149      */
150     public final boolean weakCompareAndSet(int expect, int update) {
151         return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
152     }
153 
154     /**
155      * Atomically increments by one the current value.
156      *
157      * @return the previous value
158      */
159     public final int getAndIncrement() {
160         for (;;) {
161             int current = get();
162             int next = current + 1;
163             if (compareAndSet(current, next))
164                 return current;
165         }
166     }
167 
168     /**
169      * Atomically decrements by one the current value.
170      *
171      * @return the previous value
172      */
173     public final int getAndDecrement() {
174         for (;;) {
175             int current = get();
176             int next = current - 1;
177             if (compareAndSet(current, next))
178                 return current;
179         }
180     }
181 
182     /**
183      * Atomically adds the given value to the current value.
184      *
185      * @param delta the value to add
186      * @return the previous value
187      */
188     public final int getAndAdd(int delta) {
189         for (;;) {
190             int current = get();
191             int next = current + delta;
192             if (compareAndSet(current, next))
193                 return current;
194         }
195     }
196 
197     /**
198      * Atomically increments by one the current value.
199      *
200      * @return the updated value
201      */
202     public final int incrementAndGet() {
203         for (;;) {
204             int current = get();
205             int next = current + 1;
206             if (compareAndSet(current, next))
207                 return next;
208         }
209     }
210 
211     /**
212      * Atomically decrements by one the current value.
213      *
214      * @return the updated value
215      */
216     public final int decrementAndGet() {
217         for (;;) {
218             int current = get();
219             int next = current - 1;
220             if (compareAndSet(current, next))
221                 return next;
222         }
223     }
224 
225     /**
226      * Atomically adds the given value to the current value.
227      *
228      * @param delta the value to add
229      * @return the updated value
230      */
231     public final int addAndGet(int delta) {
232         for (;;) {
233             int current = get();
234             int next = current + delta;
235             if (compareAndSet(current, next))
236                 return next;
237         }
238     }
239 
240     /**
241      * Returns the String representation of the current value.
242      * @return the String representation of the current value.
243      */
244     public String toString() {
245         return Integer.toString(get());
246     }
247 
248 
249     public int intValue() {
250         return get();
251     }
252 
253     public long longValue() {
254         return (long)get();
255     }
256 
257     public float floatValue() {
258         return (float)get();
259     }
260 
261     public double doubleValue() {
262         return (double)get();
263     }
264 
265 }
AtomicInteger

      成员变量

1 private volatile int value;//
2 private static final Unsafe unsafe = Unsafe.getUnsafe();//底层实现类unsafe
3 private static final long valueOffset;//值相对于对象的偏移量

    静态代码块(关于unsafe的objectFieldOffset这个方法可以参见另外一篇文章,链接

 static {
      try {
        //偏移量
        valueOffset = unsafe.objectFieldOffset
            (AtomicInteger.class.getDeclaredField("value")); 
      } catch (Exception ex) { throw new Error(ex); }
    }

    构造函数

 /**
     * Creates a new AtomicInteger with the given initial value.
     *
     * @param initialValue the initial value
     */
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }

    /**
     * Creates a new AtomicInteger with initial value {@code 0}.
     */
    public AtomicInteger() {
    }

   get/set方法

 /**
     * Gets the current value.
     *
     * @return the current value
     */
    public final int get() {
        return value;
    }

    /**
     * Sets to the given value.
     *
     * @param newValue the new value
     */
    public final void set(int newValue) {
        value = newValue;
    }
getAndSet
    /**
     * Atomically sets to the given value and returns the old value.
     *
     * @param newValue the new value
     * @return the previous value
     */
    public final int getAndSet(int newValue) {
        for (;;) {
            int current = get();
            if (compareAndSet(current, newValue))
                return current;
        }
    }

先调用get方法获取当前的值,然后无限循环调用compareAndSet方法来将当前的值更新为新的值,看下compareAndSet的源码

compareAndSet

  /**
     * Atomically sets the value to the given updated value
     * if the current value {@code ==} the expected value.
     *
     * @param expect the expected value
     * @param update the new value
     * @return true if successful. False return indicates that
     * the actual value was not equal to the expected value.
     */
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

可以看出调用了unsafe.compareAndSwapInt来更新值,compareAndSwapInt这个方法就是在CAS文章中提到的jdk中针对CAS,cpu指令提供的语言的实现,这个最后还是在cpu层面实现.

 继续看其他方法

getAndIncrement

    /**
     * Atomically increments by one the current value.
     *
     * @return the previous value
     */
    public final int getAndIncrement() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return current;
        }
    }

先获取当前的值,然后把当前的值增加1,然后调用compareAndSet方法将值更新为新值,一直到成功为止,返回之前的旧值

incrementAndGet

    /**
     * Atomically increments by one the current value.
     *
     * @return the updated value
     */
    public final int incrementAndGet() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return next;
        }
    }

类似getAndIncrement 但是最后返回的不是旧值而是新值,其实这个很好判断,看方法名,get在前就说明返回get的值,increment在前就说明返回increment操作以后的值

getAndAdd

    /**
     * Atomically adds the given value to the current value.
     *
     * @param delta the value to add
     * @return the previous value
     */
    public final int getAndAdd(int delta) {
        for (;;) {
            int current = get();
            int next = current + delta;
            if (compareAndSet(current, next))
                return current;
        }
    }

大同小异,只是把+1变成了加上指定的值,返回之前的值

lazzySet

    /**
     * Eventually sets to the given value.
     *
     * @param newValue the new value
     * @since 1.6
     */
    public final void lazySet(int newValue) {
        unsafe.putOrderedInt(this, valueOffset, newValue);
    }

先拿来跟set方法对比下发现lazySet的注释写的是 最终会设置成给的值(也许不保证可见性?),我们继续点到unsafe的putOrderedInt方法中可以看到

    public native void putOrderedInt(Object var1, long var2, int var4);

这个方法调用了本地方法,看不到具体实现,所以只能找找别的资料,于是我在so上搜到了这样一个解释

As probably the last little JSR166 follow-up for Mustang, we added a "lazySet" method to the Atomic classes (AtomicInteger, AtomicReference, etc). This is a niche method that is sometimes useful when fine-tuning code using non-blocking data structures. The semantics are that the write is guaranteed not to be re-ordered with any previous write, but may be reordered with subsequent operations (or equivalently, might not be visible to other threads) until some other volatile write or synchronizing action occurs).

The main use case is for nulling out fields of nodes in non-blocking data structures solely for the sake of avoiding long-term garbage retention; it applies when it is harmless if other threads see non-null values for a while, but you'd like to ensure that structures are eventually GCable. In such cases, you can get better performance by avoiding the costs of the null volatile-write. There are a few other use cases along these lines for non-reference-based atomics as well, so the method is supported across all of the AtomicX classes.

For people who like to think of these operations in terms of machine-level barriers on common multiprocessors, lazySet provides a preceeding store-store barrier (which is either a no-op or very cheap on current platforms), but no store-load barrier (which is usually the expensive part of a volatile-write).

简单来说就是lazyset这个方法是非volatile的,使用这个方法更改状态是不能保证这次更改对其他线程可见的,但是提高了更高的写入性能,所以使用见仁见智.

weekCompareAndSet

    /**
     * Atomically sets the value to the given updated value
     * if the current value {@code ==} the expected value.
     *
     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
     * and does not provide ordering guarantees, so is only rarely an
     * appropriate alternative to {@code compareAndSet}.
     *
     * @param expect the expected value
     * @param update the new value
     * @return true if successful.
     */
    public final boolean weakCompareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

这个方法很奇怪,奇怪的地方在于他的实现和compareAndSet是一毛一样的,但是上面的注释却说这个方法可能失败!!!令我十分不解,然后我去jdk文档的atomic包说明中找到了相关描述

  • 以原子方式读取和有条件地写入变量但 创建任何 happen-before 排序,因此不提供与除 weakCompareAndSet 目标外任何变量以前或后续读取或写入操作有关的任何保证。所以事情就指向了happen-before是什么鬼

继续搜 一直找到这篇文章 http://www.ibm.com/developerworks/library/j-jtp09238/index.html

Visibility failures

More subtle than atomicity failures are visibility failures. In the absence of synchronization, if one thread writes to a variable and another thread reads that same variable, the reading thread could see stale, or out-of-date, data. Worse, it is possible for the reading thread to see up-to-date data for variable x and stale data for variable y, even if y was written before x. Visibility failures are subtle because they don't happen predictably, or even frequently, causing rare and difficult-to-debug intermittent failures. Visibility failures are created by data races — failure to properly synchronize when accessing shared variables. Programs with data races are, for all intents and purposes, broken, in that their behavior cannot be reliably predicted.

The Java Memory Model (JMM) defines the conditions under which a thread reading a variable is guaranteed to see the results of a write in another thread. (A full explanation of the JMM is beyond the scope of this article; see Resources.) The JMM defines an ordering on the operations of a program called happens-before. Happens-before orderings across threads are only created by synchronizing on a common lock or accessing a common volatile variable. In the absence of a happens-before ordering, the Java platform has great latitude to delay or change the order in which writes in one thread become visible to reads of that same variable in another.

The code in Listing 2 has visibility failures as well as atomicity failures. The updateHighScore() method retrieves the HighScore object from the ServletContext and then modifies the state of the HighScore object. The intent is for those modifications to be visible to other threads that call getHighScore(), but in the absence of a happens-before ordering between the writes to the name and score properties inupdateHighScore() and the reads of those properties in other threads calling getHighScore(), we are relying on good luck for the reading threads to see the correct values.

英语不太好基本快阵亡了,不过大致还是看懂了解释,意思就是 一个线程写一个变量的值的时候要保证其他线程在读取这个值的时候是能看到写操作的(这不就是可见性么),JMM就把这一系列的操作称为happen-before,weekCompareAndSet和compareAndSet

区别在于week不会创建happen-before序列,所以也就是不提供可见性,所以有可能失败.(不过实现一毛一样是为什么!!),这个解释纯粹是自己理解,有高人可以留言解释下,实在是不太懂.

 其他方法就不分析,基本都是类似的.关于unsafe不太懂的可以去看看关于CAS的那篇文章.

至于其他原子类AtomicLong等其他基本都是unsafe的包装类,不过有点需要注意,unsafe关于cas只提供了三种

 所以很多其他的类似 AtomicBoolean 中的compareAndSet方法都是转换成unsafe.compareAndSwapInt来调用

    /**
     * Atomically sets the value to the given updated value
     * if the current value {@code ==} the expected value.
     *
     * @param expect the expected value
     * @param update the new value
     * @return true if successful. False return indicates that
     * the actual value was not equal to the expected value.
     */
    public final boolean compareAndSet(boolean expect, boolean update) {
        int e = expect ? 1 : 0;
        int u = update ? 1 : 0;
        return unsafe.compareAndSwapInt(this, valueOffset, e, u);
    }

Atomic包 大致如此...核心类还是unsafe和cas思想.

最后附上该包下面所有类的测试代码!

  1 package com.iwjw.learn.thread;
  2 
  3 import java.util.concurrent.atomic.*;
  4 
  5 /**
  6  * 原子类的包测试
  7  */
  8 public class AtomicTest {
  9     static class Student {
 10         private Long id;
 11 
 12         public Student() {
 13         }
 14 
 15         public Student(Long id) {
 16             this.id = id;
 17         }
 18 
 19         public Long getId() {
 20             return id;
 21         }
 22 
 23         public void setId(Long id) {
 24             this.id = id;
 25         }
 26     }
 27 
 28     static class Person {
 29 
 30         private int age;
 31         private String name;
 32         public volatile Student student = new Student(10086l);
 33 
 34         public volatile int length;
 35         public volatile long tall;
 36 
 37         public Person(int length) {
 38             this.length = length;
 39         }
 40 
 41         public Person(long tall) {
 42             this.tall = tall;
 43         }
 44 
 45         public Person(int age, String name) {
 46             this.age = age;
 47             this.name = name;
 48         }
 49 
 50         public Person() {
 51         }
 52 
 53         public long getTall() {
 54             return tall;
 55         }
 56 
 57         public void setTall(long tall) {
 58             this.tall = tall;
 59         }
 60 
 61         public int getLength() {
 62             return length;
 63         }
 64 
 65         public void setLength(int length) {
 66             this.length = length;
 67         }
 68 
 69         public int getAge() {
 70             return age;
 71         }
 72 
 73         public void setAge(int age) {
 74             this.age = age;
 75         }
 76 
 77         public String getName() {
 78             return name;
 79         }
 80 
 81         public void setName(String name) {
 82             this.name = name;
 83         }
 84 
 85         public Student getStudent() {
 86             return student;
 87         }
 88 
 89         public void setStudent(Student student) {
 90             this.student = student;
 91         }
 92     }
 93 
 94 
 95     public static void main(String[] args) {
 96 //        atomicIntegerTest();
 97 //        atomicLongTest();
 98 //        atomicBooleanTest();
 99 //        atomicRefTest();
100 //        atomicIntegerArrayTest();
101 //        atomicLongArrayTest();
102 //        atomicRefArrayTest();
103 //        atomicIntegerFieldUpdaterTest();
104 //        atomicLongFieldUpdaterTest();
105 //        atomicRefFieldUpdterTest();
106 //        atomicMarkableRefTest();
107 //        atomicStampedRefTest();
108     }
109 
110 
111     /**
112      * 测试 atomicInteger
113      */
114     private static void atomicIntegerTest() {
115         AtomicInteger integer = new AtomicInteger(1);
116         System.out.println("get:" + integer.get());//1
117         System.out.println("incrementAndGet:" + integer.incrementAndGet());//2
118         System.out.println("getAndIncrement:" + integer.getAndIncrement());//2
119         System.out.println("getAndSet(10):" + integer.getAndSet(10));//3
120         System.out.println("compareAndSet(10,15):" + integer.compareAndSet(10, 15));//true
121         System.out.println("compareAndSet(14,20):" + integer.compareAndSet(14, 20));//false
122         System.out.println("integer :" + integer);//15
123     }
124 
125     /**
126      * 测试 atomicLong
127      */
128     private static void atomicLongTest() {
129         AtomicLong value = new AtomicLong(1L);
130         System.out.println("get:" + value.get());//1
131         System.out.println("getAndIncrement:" + value.getAndIncrement());//1
132         System.out.println("incrementAndGet:" + value.incrementAndGet());//3
133         System.out.println("getAndSet(10):" + value.getAndSet(10l));//3
134         System.out.println("compareAndSet(10,15):" + value.compareAndSet(10, 15));//true
135         System.out.println("compareAndSet(14,20):" + value.compareAndSet(14, 20));//false
136         System.out.println("AtomicLong:" + value);//15
137 
138     }
139 
140     /**
141      * 测试 atomicBoolean
142      */
143     private static void atomicBooleanTest() {
144         AtomicBoolean value = new AtomicBoolean(false);
145         System.out.println("value:" + value.get());//false
146         System.out.println("getAndSet:" + value.getAndSet(true));//false
147         System.out.println("compareAndSet(t,f):" + value.compareAndSet(true, false));//true
148         System.out.println("AtomicBoolean:" + value);//false
149     }
150 
151     /**
152      * 测试atomicReference
153      */
154     private static void atomicRefTest() {
155         AtomicReference<AtomicTest.Person> value = new AtomicReference<Person>(new AtomicTest.Person(15, "a"));
156         Person a = value.get();
157         Person b = new Person(11, "b");
158         System.out.println("current name :" + a.getName());//a
159         System.out.println("current name getAndSet:" + value.getAndSet(b).getName());//a
160         System.out.println("current name " + value.get().getName());//b
161     }
162 
163 
164     /**
165      * 测试AtomicIntegerArray
166      */
167     private static int[] intArray = {1, 2, 3, 4, 5};
168 
169     private static void atomicIntegerArrayTest() {
170         AtomicIntegerArray array = new AtomicIntegerArray(intArray);
171         array.getAndAdd(0, 10);
172         array.getAndSet(1, 10);
173         array.incrementAndGet(2);
174         System.out.println(array.get(0));//11
175         System.out.println(array.get(1));//10
176         System.out.println(array.get(2));//4
177         System.out.println(array.compareAndSet(0, 11, 10086));//true
178         System.out.println(array.get(0));//10086
179     }
180 
181     /**
182      * 测试 AtomicLongArray
183      */
184     private static void atomicLongArrayTest() {
185         //长度 构造函数 初始化为{0,0,0,0,0.....}
186         AtomicLongArray arr = new AtomicLongArray(10);//{0,0,0,0....}
187         System.out.println("get(index):" + arr.get(0)); //0
188         System.out.println(arr.incrementAndGet(7));//1
189         System.out.println(arr.decrementAndGet(5));//-1
190         System.out.println(arr.getAndIncrement(8));//0
191         System.out.println(arr.compareAndSet(9, 0, 1));//true
192     }
193 
194 
195     /**
196      * 测试AtomicReferenceArray
197      */
198     private static void atomicRefArrayTest() {
199         AtomicReferenceArray<Person> arr = new AtomicReferenceArray<Person>(5);//[null, null, null, null, null]
200         System.out.println(arr.get(0));
201         Person a = new Person(1, "a");
202         Person b = new Person(2, "b");
203         arr.getAndSet(0, a);
204         System.out.println(arr.get(0).getName());//a
205         System.out.println(arr.compareAndSet(0, a, b));//true
206         System.out.println(arr.get(0).getName());//b
207     }
208 
209 
210     /**
211      * 测试 AtomicIntegerFieldUpdater
212      */
213     private static void atomicIntegerFieldUpdaterTest() {
214         Person a = new Person(1);
215         AtomicIntegerFieldUpdater<Person> updater = AtomicIntegerFieldUpdater.newUpdater(Person.class, "length");
216         System.out.println(updater.get(a));//1
217         System.out.println(updater.compareAndSet(a, 1, 180));//true
218         System.out.println(updater.get(a));//180
219     }
220 
221     /**
222      * 测试 AtomicLongFieldUpdater
223      */
224     private static void atomicLongFieldUpdaterTest() {
225         Person a = new Person(180l);
226         AtomicLongFieldUpdater<Person> updater = AtomicLongFieldUpdater.newUpdater(Person.class, "tall");
227         System.out.println(updater.get(a));//180
228         System.out.println(updater.compareAndSet(a, 180l, 190l));//true
229         System.out.println(updater.get(a));//190
230     }
231 
232     /**
233      * 测试 AtomicReferenceFieldUpdater
234      */
235     private static void atomicRefFieldUpdterTest() {
236         Person p = new Person();
237         AtomicReferenceFieldUpdater<Person, Student> ref = AtomicReferenceFieldUpdater.newUpdater(Person.class, Student.class, "student");
238         Student a = new Student(2l);
239         Student defaultStudent = ref.get(p);
240         System.out.println(ref.get(p).getId());//1
241         System.out.println(ref.compareAndSet(p, defaultStudent, a));//true
242         System.out.println(ref.get(p).getId());//2
243     }
244 
245 
246     /**
247      * 测试 AtomicMarkableRef
248      * 相当于AtomicReference 和 Boolean mark 2个字段的包装体
249      */
250     private static void atomicMarkableRefTest() {
251         Person a = new Person(11, "a");
252         Person b = new Person(1, "b");
253         AtomicMarkableReference<Person> ref = new AtomicMarkableReference<Person>(a, false);
254         boolean[] arr1 = {false};
255         System.out.println(ref.getReference().getName());//a
256         System.out.println(ref.get(arr1));//a
257         System.out.println(ref.attemptMark(a, false));//true
258         System.out.println(ref.isMarked());//false
259         System.out.println(ref.compareAndSet(a, b, false, true));//true
260         System.out.println(ref.getReference().getName());//b
261         System.out.println(ref.isMarked());//true
262     }
263 
264 
265     /**
266      * 测试 AtomicStampedRef
267      * 相当于atomicReference 和一个Integer 的包装
268      */
269     private static void atomicStampedRefTest() {
270 
271         Person a = new Person(11, "a");
272         Person b = new Person(1, "b");
273         AtomicStampedReference<Person> ref = new AtomicStampedReference<Person>(a, 0);
274         int[] arr = {10};
275         System.out.println(ref.getReference().getName());//a
276         System.out.println(ref.getStamp());//0
277         System.out.println(ref.get(arr));//a
278         System.out.println(ref.attemptStamp(a, 10));//true
279         System.out.println(ref.getStamp());//10
280         System.out.println(ref.compareAndSet(a, b, 10, 10086));//true
281         System.out.println(ref.getStamp());//10086
282     }
283 
284 }
atomic包所有类的测试代码
原文地址:https://www.cnblogs.com/coldridgeValley/p/4979537.html