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.LongBinaryOperator; 10 import java.util.function.LongUnaryOperator; 11 12 /** 13 * A {@code long} value that may be updated atomically. See the 14 * {@link java.util.concurrent.atomic} package specification for 15 * description of the properties of atomic variables. An 16 * {@code AtomicLong} is used in applications such as atomically 17 * incremented sequence numbers, and cannot be used as a replacement 18 * for a {@link java.lang.Long}. However, this class does extend 19 * {@code Number} to allow uniform access by tools and utilities that 20 * deal with numerically-based classes. 21 * 22 * @since 1.5 23 * @author Doug Lea 24 */ 25 public class AtomicLong extends Number implements java.io.Serializable { 26 private static final long serialVersionUID = 1927816293512124184L; 27 28 private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); 29 private static final long VALUE; 30 31 /** 32 * Records whether the underlying JVM supports lockless 33 * compareAndSwap for longs. While the Unsafe.compareAndSwapLong 34 * method works in either case, some constructions should be 35 * handled at Java level to avoid locking user-visible locks. 36 */ 37 static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8(); 38 39 /** 40 * Returns whether underlying JVM supports lockless CompareAndSet 41 * for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS. 42 */ VMSupportsCS8()43 private static native boolean VMSupportsCS8(); 44 45 static { 46 try { 47 VALUE = U.objectFieldOffset 48 (AtomicLong.class.getDeclaredField("value")); 49 } catch (ReflectiveOperationException e) { 50 throw new Error(e); 51 } 52 } 53 54 private volatile long value; 55 56 /** 57 * Creates a new AtomicLong with the given initial value. 58 * 59 * @param initialValue the initial value 60 */ AtomicLong(long initialValue)61 public AtomicLong(long initialValue) { 62 value = initialValue; 63 } 64 65 /** 66 * Creates a new AtomicLong with initial value {@code 0}. 67 */ AtomicLong()68 public AtomicLong() { 69 } 70 71 /** 72 * Gets the current value. 73 * 74 * @return the current value 75 */ get()76 public final long get() { 77 return value; 78 } 79 80 /** 81 * Sets to the given value. 82 * 83 * @param newValue the new value 84 */ set(long newValue)85 public final void set(long newValue) { 86 // Use putLongVolatile instead of ordinary volatile store when 87 // using compareAndSwapLong, for sake of some 32bit systems. 88 U.putLongVolatile(this, VALUE, newValue); 89 } 90 91 /** 92 * Eventually sets to the given value. 93 * 94 * @param newValue the new value 95 * @since 1.6 96 */ lazySet(long newValue)97 public final void lazySet(long newValue) { 98 U.putOrderedLong(this, VALUE, newValue); 99 } 100 101 /** 102 * Atomically sets to the given value and returns the old value. 103 * 104 * @param newValue the new value 105 * @return the previous value 106 */ getAndSet(long newValue)107 public final long getAndSet(long newValue) { 108 return U.getAndSetLong(this, VALUE, newValue); 109 } 110 111 /** 112 * Atomically sets the value to the given updated value 113 * if the current value {@code ==} the expected value. 114 * 115 * @param expect the expected value 116 * @param update the new value 117 * @return {@code true} if successful. False return indicates that 118 * the actual value was not equal to the expected value. 119 */ compareAndSet(long expect, long update)120 public final boolean compareAndSet(long expect, long update) { 121 return U.compareAndSwapLong(this, VALUE, expect, update); 122 } 123 124 /** 125 * Atomically sets the value to the given updated value 126 * if the current value {@code ==} the expected value. 127 * 128 * <p><a href="package-summary.html#weakCompareAndSet">May fail 129 * spuriously and does not provide ordering guarantees</a>, so is 130 * only rarely an appropriate alternative to {@code compareAndSet}. 131 * 132 * @param expect the expected value 133 * @param update the new value 134 * @return {@code true} if successful 135 */ weakCompareAndSet(long expect, long update)136 public final boolean weakCompareAndSet(long expect, long update) { 137 return U.compareAndSwapLong(this, VALUE, expect, update); 138 } 139 140 /** 141 * Atomically increments by one the current value. 142 * 143 * @return the previous value 144 */ getAndIncrement()145 public final long getAndIncrement() { 146 return U.getAndAddLong(this, VALUE, 1L); 147 } 148 149 /** 150 * Atomically decrements by one the current value. 151 * 152 * @return the previous value 153 */ getAndDecrement()154 public final long getAndDecrement() { 155 return U.getAndAddLong(this, VALUE, -1L); 156 } 157 158 /** 159 * Atomically adds the given value to the current value. 160 * 161 * @param delta the value to add 162 * @return the previous value 163 */ getAndAdd(long delta)164 public final long getAndAdd(long delta) { 165 return U.getAndAddLong(this, VALUE, delta); 166 } 167 168 /** 169 * Atomically increments by one the current value. 170 * 171 * @return the updated value 172 */ incrementAndGet()173 public final long incrementAndGet() { 174 return U.getAndAddLong(this, VALUE, 1L) + 1L; 175 } 176 177 /** 178 * Atomically decrements by one the current value. 179 * 180 * @return the updated value 181 */ decrementAndGet()182 public final long decrementAndGet() { 183 return U.getAndAddLong(this, VALUE, -1L) - 1L; 184 } 185 186 /** 187 * Atomically adds the given value to the current value. 188 * 189 * @param delta the value to add 190 * @return the updated value 191 */ addAndGet(long delta)192 public final long addAndGet(long delta) { 193 return U.getAndAddLong(this, VALUE, delta) + delta; 194 } 195 196 /** 197 * Atomically updates the current value with the results of 198 * applying the given function, returning the previous value. The 199 * function should be side-effect-free, since it may be re-applied 200 * when attempted updates fail due to contention among threads. 201 * 202 * @param updateFunction a side-effect-free function 203 * @return the previous value 204 * @since 1.8 205 */ getAndUpdate(LongUnaryOperator updateFunction)206 public final long getAndUpdate(LongUnaryOperator updateFunction) { 207 long prev, next; 208 do { 209 prev = get(); 210 next = updateFunction.applyAsLong(prev); 211 } while (!compareAndSet(prev, next)); 212 return prev; 213 } 214 215 /** 216 * Atomically updates the current value with the results of 217 * applying the given function, returning the updated value. The 218 * function should be side-effect-free, since it may be re-applied 219 * when attempted updates fail due to contention among threads. 220 * 221 * @param updateFunction a side-effect-free function 222 * @return the updated value 223 * @since 1.8 224 */ updateAndGet(LongUnaryOperator updateFunction)225 public final long updateAndGet(LongUnaryOperator updateFunction) { 226 long prev, next; 227 do { 228 prev = get(); 229 next = updateFunction.applyAsLong(prev); 230 } while (!compareAndSet(prev, next)); 231 return next; 232 } 233 234 /** 235 * Atomically updates the current value with the results of 236 * applying the given function to the current and given values, 237 * returning the previous value. The function should be 238 * side-effect-free, since it may be re-applied when attempted 239 * updates fail due to contention among threads. The function 240 * is applied with the current value as its first argument, 241 * and the given update as the second argument. 242 * 243 * @param x the update value 244 * @param accumulatorFunction a side-effect-free function of two arguments 245 * @return the previous value 246 * @since 1.8 247 */ getAndAccumulate(long x, LongBinaryOperator accumulatorFunction)248 public final long getAndAccumulate(long x, 249 LongBinaryOperator accumulatorFunction) { 250 long prev, next; 251 do { 252 prev = get(); 253 next = accumulatorFunction.applyAsLong(prev, x); 254 } while (!compareAndSet(prev, next)); 255 return prev; 256 } 257 258 /** 259 * Atomically updates the current value with the results of 260 * applying the given function to the current and given values, 261 * returning the updated value. The function should be 262 * side-effect-free, since it may be re-applied when attempted 263 * updates fail due to contention among threads. The function 264 * is applied with the current value as its first argument, 265 * and the given update as the second argument. 266 * 267 * @param x the update value 268 * @param accumulatorFunction a side-effect-free function of two arguments 269 * @return the updated value 270 * @since 1.8 271 */ accumulateAndGet(long x, LongBinaryOperator accumulatorFunction)272 public final long accumulateAndGet(long x, 273 LongBinaryOperator accumulatorFunction) { 274 long prev, next; 275 do { 276 prev = get(); 277 next = accumulatorFunction.applyAsLong(prev, x); 278 } while (!compareAndSet(prev, next)); 279 return next; 280 } 281 282 /** 283 * Returns the String representation of the current value. 284 * @return the String representation of the current value 285 */ toString()286 public String toString() { 287 return Long.toString(get()); 288 } 289 290 /** 291 * Returns the value of this {@code AtomicLong} as an {@code int} 292 * after a narrowing primitive conversion. 293 * @jls 5.1.3 Narrowing Primitive Conversions 294 */ intValue()295 public int intValue() { 296 return (int)get(); 297 } 298 299 /** 300 * Returns the value of this {@code AtomicLong} as a {@code long}. 301 * Equivalent to {@link #get()}. 302 */ longValue()303 public long longValue() { 304 return get(); 305 } 306 307 /** 308 * Returns the value of this {@code AtomicLong} as a {@code float} 309 * after a widening primitive conversion. 310 * @jls 5.1.2 Widening Primitive Conversions 311 */ floatValue()312 public float floatValue() { 313 return (float)get(); 314 } 315 316 /** 317 * Returns the value of this {@code AtomicLong} as a {@code double} 318 * after a widening primitive conversion. 319 * @jls 5.1.2 Widening Primitive Conversions 320 */ doubleValue()321 public double doubleValue() { 322 return (double)get(); 323 } 324 325 } 326