View Javadoc
1   /*
2    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3    *
4    * This code is free software; you can redistribute it and/or modify it
5    * under the terms of the GNU General Public License version 2 only, as
6    * published by the Free Software Foundation.  Oracle designates this
7    * particular file as subject to the "Classpath" exception as provided
8    * by Oracle in the LICENSE file that accompanied this code.
9    *
10   * This code is distributed in the hope that it will be useful, but WITHOUT
11   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13   * version 2 for more details (a copy is included in the LICENSE file that
14   * accompanied this code).
15   *
16   * You should have received a copy of the GNU General Public License version
17   * 2 along with this work; if not, write to the Free Software Foundation,
18   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19   *
20   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21   * or visit www.oracle.com if you need additional information or have any
22   * questions.
23   */
24  
25  /*
26   * This file is available under and governed by the GNU General Public
27   * License version 2 only, as published by the Free Software Foundation.
28   * However, the following notice accompanied the original version of this
29   * file:
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 java.util.function.LongUnaryOperator;
38  import java.util.function.LongBinaryOperator;
39  import sun.misc.Unsafe;
40  
41  /**
42   * A {@code long} value that may be updated atomically.  See the
43   * {@link java.util.concurrent.atomic} package specification for
44   * description of the properties of atomic variables. An
45   * {@code AtomicLong} is used in applications such as atomically
46   * incremented sequence numbers, and cannot be used as a replacement
47   * for a {@link java.lang.Long}. However, this class does extend
48   * {@code Number} to allow uniform access by tools and utilities that
49   * deal with numerically-based classes.
50   *
51   * @since 1.5
52   * @author Doug Lea
53   */
54  public class AtomicLong extends Number implements java.io.Serializable {
55      private static final long serialVersionUID = 1927816293512124184L;
56  
57      // setup to use Unsafe.compareAndSwapLong for updates
58      private static final Unsafe unsafe = Unsafe.getUnsafe();
59      private static final long valueOffset;
60  
61      /**
62       * Records whether the underlying JVM supports lockless
63       * compareAndSwap for longs. While the Unsafe.compareAndSwapLong
64       * method works in either case, some constructions should be
65       * handled at Java level to avoid locking user-visible locks.
66       */
67      static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
68  
69      /**
70       * Returns whether underlying JVM supports lockless CompareAndSet
71       * for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.
72       */
73      private static native boolean VMSupportsCS8();
74  
75      static {
76          try {
77              valueOffset = unsafe.objectFieldOffset
78                  (AtomicLong.class.getDeclaredField("value"));
79          } catch (Exception ex) { throw new Error(ex); }
80      }
81  
82      private volatile long value;
83  
84      /**
85       * Creates a new AtomicLong with the given initial value.
86       *
87       * @param initialValue the initial value
88       */
89      public AtomicLong(long initialValue) {
90          value = initialValue;
91      }
92  
93      /**
94       * Creates a new AtomicLong with initial value {@code 0}.
95       */
96      public AtomicLong() {
97      }
98  
99      /**
100      * Gets the current value.
101      *
102      * @return the current value
103      */
104     public final long get() {
105         return value;
106     }
107 
108     /**
109      * Sets to the given value.
110      *
111      * @param newValue the new value
112      */
113     public final void set(long newValue) {
114         value = newValue;
115     }
116 
117     /**
118      * Eventually sets to the given value.
119      *
120      * @param newValue the new value
121      * @since 1.6
122      */
123     public final void lazySet(long newValue) {
124         unsafe.putOrderedLong(this, valueOffset, newValue);
125     }
126 
127     /**
128      * Atomically sets to the given value and returns the old value.
129      *
130      * @param newValue the new value
131      * @return the previous value
132      */
133     public final long getAndSet(long newValue) {
134         return unsafe.getAndSetLong(this, valueOffset, newValue);
135     }
136 
137     /**
138      * Atomically sets the value to the given updated value
139      * if the current value {@code ==} the expected value.
140      *
141      * @param expect the expected value
142      * @param update the new value
143      * @return {@code true} if successful. False return indicates that
144      * the actual value was not equal to the expected value.
145      */
146     public final boolean compareAndSet(long expect, long update) {
147         return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
148     }
149 
150     /**
151      * Atomically sets the value to the given updated value
152      * if the current value {@code ==} the expected value.
153      *
154      * <p><a href="package-summary.html#weakCompareAndSet">May fail
155      * spuriously and does not provide ordering guarantees</a>, so is
156      * only rarely an appropriate alternative to {@code compareAndSet}.
157      *
158      * @param expect the expected value
159      * @param update the new value
160      * @return {@code true} if successful
161      */
162     public final boolean weakCompareAndSet(long expect, long update) {
163         return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
164     }
165 
166     /**
167      * Atomically increments by one the current value.
168      *
169      * @return the previous value
170      */
171     public final long getAndIncrement() {
172         return unsafe.getAndAddLong(this, valueOffset, 1L);
173     }
174 
175     /**
176      * Atomically decrements by one the current value.
177      *
178      * @return the previous value
179      */
180     public final long getAndDecrement() {
181         return unsafe.getAndAddLong(this, valueOffset, -1L);
182     }
183 
184     /**
185      * Atomically adds the given value to the current value.
186      *
187      * @param delta the value to add
188      * @return the previous value
189      */
190     public final long getAndAdd(long delta) {
191         return unsafe.getAndAddLong(this, valueOffset, delta);
192     }
193 
194     /**
195      * Atomically increments by one the current value.
196      *
197      * @return the updated value
198      */
199     public final long incrementAndGet() {
200         return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L;
201     }
202 
203     /**
204      * Atomically decrements by one the current value.
205      *
206      * @return the updated value
207      */
208     public final long decrementAndGet() {
209         return unsafe.getAndAddLong(this, valueOffset, -1L) - 1L;
210     }
211 
212     /**
213      * Atomically adds the given value to the current value.
214      *
215      * @param delta the value to add
216      * @return the updated value
217      */
218     public final long addAndGet(long delta) {
219         return unsafe.getAndAddLong(this, valueOffset, delta) + delta;
220     }
221 
222     /**
223      * Atomically updates the current value with the results of
224      * applying the given function, returning the previous value. The
225      * function should be side-effect-free, since it may be re-applied
226      * when attempted updates fail due to contention among threads.
227      *
228      * @param updateFunction a side-effect-free function
229      * @return the previous value
230      * @since 1.8
231      */
232     public final long getAndUpdate(LongUnaryOperator updateFunction) {
233         long prev, next;
234         do {
235             prev = get();
236             next = updateFunction.applyAsLong(prev);
237         } while (!compareAndSet(prev, next));
238         return prev;
239     }
240 
241     /**
242      * Atomically updates the current value with the results of
243      * applying the given function, returning the updated value. The
244      * function should be side-effect-free, since it may be re-applied
245      * when attempted updates fail due to contention among threads.
246      *
247      * @param updateFunction a side-effect-free function
248      * @return the updated value
249      * @since 1.8
250      */
251     public final long updateAndGet(LongUnaryOperator updateFunction) {
252         long prev, next;
253         do {
254             prev = get();
255             next = updateFunction.applyAsLong(prev);
256         } while (!compareAndSet(prev, next));
257         return next;
258     }
259 
260     /**
261      * Atomically updates the current value with the results of
262      * applying the given function to the current and given values,
263      * returning the previous value. The function should be
264      * side-effect-free, since it may be re-applied when attempted
265      * updates fail due to contention among threads.  The function
266      * is applied with the current value as its first argument,
267      * and the given update as the second argument.
268      *
269      * @param x the update value
270      * @param accumulatorFunction a side-effect-free function of two arguments
271      * @return the previous value
272      * @since 1.8
273      */
274     public final long getAndAccumulate(long x,
275                                        LongBinaryOperator accumulatorFunction) {
276         long prev, next;
277         do {
278             prev = get();
279             next = accumulatorFunction.applyAsLong(prev, x);
280         } while (!compareAndSet(prev, next));
281         return prev;
282     }
283 
284     /**
285      * Atomically updates the current value with the results of
286      * applying the given function to the current and given values,
287      * returning the updated value. The function should be
288      * side-effect-free, since it may be re-applied when attempted
289      * updates fail due to contention among threads.  The function
290      * is applied with the current value as its first argument,
291      * and the given update as the second argument.
292      *
293      * @param x the update value
294      * @param accumulatorFunction a side-effect-free function of two arguments
295      * @return the updated value
296      * @since 1.8
297      */
298     public final long accumulateAndGet(long x,
299                                        LongBinaryOperator accumulatorFunction) {
300         long prev, next;
301         do {
302             prev = get();
303             next = accumulatorFunction.applyAsLong(prev, x);
304         } while (!compareAndSet(prev, next));
305         return next;
306     }
307 
308     /**
309      * Returns the String representation of the current value.
310      * @return the String representation of the current value
311      */
312     public String toString() {
313         return Long.toString(get());
314     }
315 
316     /**
317      * Returns the value of this {@code AtomicLong} as an {@code int}
318      * after a narrowing primitive conversion.
319      * @jls 5.1.3 Narrowing Primitive Conversions
320      */
321     public int intValue() {
322         return (int)get();
323     }
324 
325     /**
326      * Returns the value of this {@code AtomicLong} as a {@code long}.
327      */
328     public long longValue() {
329         return get();
330     }
331 
332     /**
333      * Returns the value of this {@code AtomicLong} as a {@code float}
334      * after a widening primitive conversion.
335      * @jls 5.1.2 Widening Primitive Conversions
336      */
337     public float floatValue() {
338         return (float)get();
339     }
340 
341     /**
342      * Returns the value of this {@code AtomicLong} as a {@code double}
343      * after a widening primitive conversion.
344      * @jls 5.1.2 Widening Primitive Conversions
345      */
346     public double doubleValue() {
347         return (double)get();
348     }
349 
350 }