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