1 /* 2 * Written by Doug Lea with assistance from members of JCP JSR-166 3 * Expert Group and released to the public domain, as explained at 4 * http://creativecommons.org/publicdomain/zero/1.0/ 5 */ 6 7 package java.util.concurrent.atomic; 8 9 import java.util.function.BinaryOperator; 10 import java.util.function.UnaryOperator; 11 12 /** 13 * An object reference that may be updated atomically. See the {@link 14 * java.util.concurrent.atomic} package specification for description 15 * of the properties of atomic variables. 16 * @since 1.5 17 * @author Doug Lea 18 * @param <V> The type of object referred to by this reference 19 */ 20 public class AtomicReference<V> implements java.io.Serializable { 21 private static final long serialVersionUID = -1848883965231344442L; 22 23 private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); 24 private static final long VALUE; 25 26 static { 27 try { 28 VALUE = U.objectFieldOffset 29 (AtomicReference.class.getDeclaredField("value")); 30 } catch (ReflectiveOperationException e) { 31 throw new Error(e); 32 } 33 } 34 35 private volatile V value; 36 37 /** 38 * Creates a new AtomicReference with the given initial value. 39 * 40 * @param initialValue the initial value 41 */ AtomicReference(V initialValue)42 public AtomicReference(V initialValue) { 43 value = initialValue; 44 } 45 46 /** 47 * Creates a new AtomicReference with null initial value. 48 */ AtomicReference()49 public AtomicReference() { 50 } 51 52 /** 53 * Gets the current value. 54 * 55 * @return the current value 56 */ get()57 public final V get() { 58 return value; 59 } 60 61 /** 62 * Sets to the given value. 63 * 64 * @param newValue the new value 65 */ set(V newValue)66 public final void set(V newValue) { 67 value = newValue; 68 } 69 70 /** 71 * Eventually sets to the given value. 72 * 73 * @param newValue the new value 74 * @since 1.6 75 */ lazySet(V newValue)76 public final void lazySet(V newValue) { 77 U.putOrderedObject(this, VALUE, newValue); 78 } 79 80 /** 81 * Atomically sets the value to the given updated value 82 * if the current value {@code ==} the expected value. 83 * @param expect the expected value 84 * @param update the new value 85 * @return {@code true} if successful. False return indicates that 86 * the actual value was not equal to the expected value. 87 */ compareAndSet(V expect, V update)88 public final boolean compareAndSet(V expect, V update) { 89 return U.compareAndSwapObject(this, VALUE, expect, update); 90 } 91 92 /** 93 * Atomically sets the value to the given updated value 94 * if the current value {@code ==} the expected value. 95 * 96 * <p><a href="package-summary.html#weakCompareAndSet">May fail 97 * spuriously and does not provide ordering guarantees</a>, so is 98 * only rarely an appropriate alternative to {@code compareAndSet}. 99 * 100 * @param expect the expected value 101 * @param update the new value 102 * @return {@code true} if successful 103 */ weakCompareAndSet(V expect, V update)104 public final boolean weakCompareAndSet(V expect, V update) { 105 return U.compareAndSwapObject(this, VALUE, expect, update); 106 } 107 108 /** 109 * Atomically sets to the given value and returns the old value. 110 * 111 * @param newValue the new value 112 * @return the previous value 113 */ 114 @SuppressWarnings("unchecked") getAndSet(V newValue)115 public final V getAndSet(V newValue) { 116 return (V)U.getAndSetObject(this, VALUE, newValue); 117 } 118 119 /** 120 * Atomically updates the current value with the results of 121 * applying the given function, returning the previous value. The 122 * function should be side-effect-free, since it may be re-applied 123 * when attempted updates fail due to contention among threads. 124 * 125 * @param updateFunction a side-effect-free function 126 * @return the previous value 127 * @since 1.8 128 */ getAndUpdate(UnaryOperator<V> updateFunction)129 public final V getAndUpdate(UnaryOperator<V> updateFunction) { 130 V prev, next; 131 do { 132 prev = get(); 133 next = updateFunction.apply(prev); 134 } while (!compareAndSet(prev, next)); 135 return prev; 136 } 137 138 /** 139 * Atomically updates the current value with the results of 140 * applying the given function, returning the updated value. The 141 * function should be side-effect-free, since it may be re-applied 142 * when attempted updates fail due to contention among threads. 143 * 144 * @param updateFunction a side-effect-free function 145 * @return the updated value 146 * @since 1.8 147 */ updateAndGet(UnaryOperator<V> updateFunction)148 public final V updateAndGet(UnaryOperator<V> updateFunction) { 149 V prev, next; 150 do { 151 prev = get(); 152 next = updateFunction.apply(prev); 153 } while (!compareAndSet(prev, next)); 154 return next; 155 } 156 157 /** 158 * Atomically updates the current value with the results of 159 * applying the given function to the current and given values, 160 * returning the previous value. The function should be 161 * side-effect-free, since it may be re-applied when attempted 162 * updates fail due to contention among threads. The function 163 * is applied with the current value as its first argument, 164 * and the given update as the second argument. 165 * 166 * @param x the update value 167 * @param accumulatorFunction a side-effect-free function of two arguments 168 * @return the previous value 169 * @since 1.8 170 */ getAndAccumulate(V x, BinaryOperator<V> accumulatorFunction)171 public final V getAndAccumulate(V x, 172 BinaryOperator<V> accumulatorFunction) { 173 V prev, next; 174 do { 175 prev = get(); 176 next = accumulatorFunction.apply(prev, x); 177 } while (!compareAndSet(prev, next)); 178 return prev; 179 } 180 181 /** 182 * Atomically updates the current value with the results of 183 * applying the given function to the current and given values, 184 * returning the updated value. The function should be 185 * side-effect-free, since it may be re-applied when attempted 186 * updates fail due to contention among threads. The function 187 * is applied with the current value as its first argument, 188 * and the given update as the second argument. 189 * 190 * @param x the update value 191 * @param accumulatorFunction a side-effect-free function of two arguments 192 * @return the updated value 193 * @since 1.8 194 */ accumulateAndGet(V x, BinaryOperator<V> accumulatorFunction)195 public final V accumulateAndGet(V x, 196 BinaryOperator<V> accumulatorFunction) { 197 V prev, next; 198 do { 199 prev = get(); 200 next = accumulatorFunction.apply(prev, x); 201 } while (!compareAndSet(prev, next)); 202 return next; 203 } 204 205 /** 206 * Returns the String representation of the current value. 207 * @return the String representation of the current value 208 */ toString()209 public String toString() { 210 return String.valueOf(get()); 211 } 212 213 } 214