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/licenses/publicdomain 5 */ 6 7package java.util.concurrent.atomic; 8import 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 */ 23public 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 // BEGIN android-changed 28 private static final Unsafe unsafe = UnsafeAccess.THE_ONE; 29 // END android-changed 30 private static final long valueOffset; 31 32 /** 33 * Records whether the underlying JVM supports lockless 34 * compareAndSwap for longs. While the Unsafe.compareAndSwapLong 35 * method works in either case, some constructions should be 36 * handled at Java level to avoid locking user-visible locks. 37 * 38 * Initialised in the static block. 39 */ 40 static final boolean VM_SUPPORTS_LONG_CAS; 41 42 /** 43 * Returns whether underlying JVM supports lockless CompareAndSet 44 * for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS. 45 */ 46 private static native boolean VMSupportsCS8(); 47 48 static { 49 try { 50 valueOffset = unsafe.objectFieldOffset 51 (AtomicLong.class.getDeclaredField("value")); 52 } catch (Exception ex) { throw new Error(ex); } 53 54 boolean longCASSupport; 55 try { 56 longCASSupport = VMSupportsCS8(); 57 } catch (UnsatisfiedLinkError e) { 58 // assume there's support if the native isn't provided by the VM 59 longCASSupport = true; 60 } 61 VM_SUPPORTS_LONG_CAS = longCASSupport; 62 } 63 64 private volatile long value; 65 66 /** 67 * Creates a new AtomicLong with the given initial value. 68 * 69 * @param initialValue the initial value 70 */ 71 public AtomicLong(long initialValue) { 72 value = initialValue; 73 } 74 75 /** 76 * Creates a new AtomicLong with initial value {@code 0}. 77 */ 78 public AtomicLong() { 79 } 80 81 /** 82 * Gets the current value. 83 * 84 * @return the current value 85 */ 86 public final long get() { 87 return value; 88 } 89 90 /** 91 * Sets to the given value. 92 * 93 * @param newValue the new value 94 */ 95 public final void set(long newValue) { 96 value = newValue; 97 } 98 99 /** 100 * Atomically sets to the given value and returns the old value. 101 * 102 * @param newValue the new value 103 * @return the previous value 104 */ 105 public final long getAndSet(long newValue) { 106 while (true) { 107 long current = get(); 108 if (compareAndSet(current, newValue)) 109 return current; 110 } 111 } 112 113 /** 114 * Atomically sets the value to the given updated value 115 * if the current value {@code ==} the expected value. 116 * 117 * @param expect the expected value 118 * @param update the new value 119 * @return true if successful. False return indicates that 120 * the actual value was not equal to the expected value. 121 */ 122 public final boolean compareAndSet(long expect, long update) { 123 return unsafe.compareAndSwapLong(this, valueOffset, expect, update); 124 } 125 126 /** 127 * Atomically sets the value to the given updated value 128 * if the current value {@code ==} the expected value. 129 * 130 * <p>May <a href="package-summary.html#Spurious">fail spuriously</a> 131 * and does not provide ordering guarantees, so is only rarely an 132 * appropriate alternative to {@code compareAndSet}. 133 * 134 * @param expect the expected value 135 * @param update the new value 136 * @return true if successful. 137 */ 138 public final boolean weakCompareAndSet(long expect, long update) { 139 return unsafe.compareAndSwapLong(this, valueOffset, expect, update); 140 } 141 142 /** 143 * Atomically increments by one the current value. 144 * 145 * @return the previous value 146 */ 147 public final long getAndIncrement() { 148 while (true) { 149 long current = get(); 150 long next = current + 1; 151 if (compareAndSet(current, next)) 152 return current; 153 } 154 } 155 156 /** 157 * Atomically decrements by one the current value. 158 * 159 * @return the previous value 160 */ 161 public final long getAndDecrement() { 162 while (true) { 163 long current = get(); 164 long next = current - 1; 165 if (compareAndSet(current, next)) 166 return current; 167 } 168 } 169 170 /** 171 * Atomically adds the given value to the current value. 172 * 173 * @param delta the value to add 174 * @return the previous value 175 */ 176 public final long getAndAdd(long delta) { 177 while (true) { 178 long current = get(); 179 long next = current + delta; 180 if (compareAndSet(current, next)) 181 return current; 182 } 183 } 184 185 /** 186 * Atomically increments by one the current value. 187 * 188 * @return the updated value 189 */ 190 public final long incrementAndGet() { 191 for (;;) { 192 long current = get(); 193 long next = current + 1; 194 if (compareAndSet(current, next)) 195 return next; 196 } 197 } 198 199 /** 200 * Atomically decrements by one the current value. 201 * 202 * @return the updated value 203 */ 204 public final long decrementAndGet() { 205 for (;;) { 206 long current = get(); 207 long next = current - 1; 208 if (compareAndSet(current, next)) 209 return next; 210 } 211 } 212 213 /** 214 * Atomically adds the given value to the current value. 215 * 216 * @param delta the value to add 217 * @return the updated value 218 */ 219 public final long addAndGet(long delta) { 220 for (;;) { 221 long current = get(); 222 long next = current + delta; 223 if (compareAndSet(current, next)) 224 return next; 225 } 226 } 227 228 /** 229 * Returns the String representation of the current value. 230 * @return the String representation of the current value. 231 */ 232 public String toString() { 233 return Long.toString(get()); 234 } 235 236 237 public int intValue() { 238 return (int)get(); 239 } 240 241 public long longValue() { 242 return get(); 243 } 244 245 public float floatValue() { 246 return (float)get(); 247 } 248 249 public double doubleValue() { 250 return (double)get(); 251 } 252 253} 254