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.IntUnaryOperator;
38  import java.util.function.IntBinaryOperator;
39  import sun.misc.Unsafe;
40  
41  /**
42   * An {@code int} 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 AtomicInteger} is used in applications such as atomically
46   * incremented counters, and cannot be used as a replacement for an
47   * {@link java.lang.Integer}. 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 AtomicInteger extends Number implements java.io.Serializable {
55      private static final long serialVersionUID = 6214790243416807050L;
56  
57      // setup to use Unsafe.compareAndSwapInt for updates
58      private static final Unsafe unsafe = Unsafe.getUnsafe();
59      private static final long valueOffset;
60  
61      static {
62          try {
63              valueOffset = unsafe.objectFieldOffset
64                  (AtomicInteger.class.getDeclaredField("value"));
65          } catch (Exception ex) { throw new Error(ex); }
66      }
67  
68      private volatile int value;
69  
70      /**
71       * Creates a new AtomicInteger with the given initial value.
72       *
73       * @param initialValue the initial value
74       */
75      public AtomicInteger(int initialValue) {
76          value = initialValue;
77      }
78  
79      /**
80       * Creates a new AtomicInteger with initial value {@code 0}.
81       */
82      public AtomicInteger() {
83      }
84  
85      /**
86       * Gets the current value.
87       *
88       * @return the current value
89       */
90      public final int get() {
91          return value;
92      }
93  
94      /**
95       * Sets to the given value.
96       *
97       * @param newValue the new value
98       */
99      public final void set(int newValue) {
100         value = newValue;
101     }
102 
103     /**
104      * Eventually sets to the given value.
105      *
106      * @param newValue the new value
107      * @since 1.6
108      */
109     public final void lazySet(int newValue) {
110         unsafe.putOrderedInt(this, valueOffset, newValue);
111     }
112 
113     /**
114      * Atomically sets to the given value and returns the old value.
115      *
116      * @param newValue the new value
117      * @return the previous value
118      */
119     public final int getAndSet(int newValue) {
120         return unsafe.getAndSetInt(this, valueOffset, newValue);
121     }
122 
123     /**
124      * Atomically sets the value to the given updated value
125      * if the current value {@code ==} the expected value.
126      *
127      * @param expect the expected value
128      * @param update the new value
129      * @return {@code true} if successful. False return indicates that
130      * the actual value was not equal to the expected value.
131      */
132     public final boolean compareAndSet(int expect, int update) {
133         return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
134     }
135 
136     /**
137      * Atomically sets the value to the given updated value
138      * if the current value {@code ==} the expected value.
139      *
140      * <p><a href="package-summary.html#weakCompareAndSet">May fail
141      * spuriously and does not provide ordering guarantees</a>, so is
142      * only rarely an appropriate alternative to {@code compareAndSet}.
143      *
144      * @param expect the expected value
145      * @param update the new value
146      * @return {@code true} if successful
147      */
148     public final boolean weakCompareAndSet(int expect, int update) {
149         return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
150     }
151 
152     /**
153      * Atomically increments by one the current value.
154      *
155      * @return the previous value
156      */
157     public final int getAndIncrement() {
158         return unsafe.getAndAddInt(this, valueOffset, 1);
159     }
160 
161     /**
162      * Atomically decrements by one the current value.
163      *
164      * @return the previous value
165      */
166     public final int getAndDecrement() {
167         return unsafe.getAndAddInt(this, valueOffset, -1);
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 int getAndAdd(int delta) {
177         return unsafe.getAndAddInt(this, valueOffset, delta);
178     }
179 
180     /**
181      * Atomically increments by one the current value.
182      *
183      * @return the updated value
184      */
185     public final int incrementAndGet() {
186         return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
187     }
188 
189     /**
190      * Atomically decrements by one the current value.
191      *
192      * @return the updated value
193      */
194     public final int decrementAndGet() {
195         return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
196     }
197 
198     /**
199      * Atomically adds the given value to the current value.
200      *
201      * @param delta the value to add
202      * @return the updated value
203      */
204     public final int addAndGet(int delta) {
205         return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
206     }
207 
208     /**
209      * Atomically updates the current value with the results of
210      * applying the given function, returning the previous value. The
211      * function should be side-effect-free, since it may be re-applied
212      * when attempted updates fail due to contention among threads.
213      *
214      * @param updateFunction a side-effect-free function
215      * @return the previous value
216      * @since 1.8
217      */
218     public final int getAndUpdate(IntUnaryOperator updateFunction) {
219         int prev, next;
220         do {
221             prev = get();
222             next = updateFunction.applyAsInt(prev);
223         } while (!compareAndSet(prev, next));
224         return prev;
225     }
226 
227     /**
228      * Atomically updates the current value with the results of
229      * applying the given function, returning the updated value. The
230      * function should be side-effect-free, since it may be re-applied
231      * when attempted updates fail due to contention among threads.
232      *
233      * @param updateFunction a side-effect-free function
234      * @return the updated value
235      * @since 1.8
236      */
237     public final int updateAndGet(IntUnaryOperator updateFunction) {
238         int prev, next;
239         do {
240             prev = get();
241             next = updateFunction.applyAsInt(prev);
242         } while (!compareAndSet(prev, next));
243         return next;
244     }
245 
246     /**
247      * Atomically updates the current value with the results of
248      * applying the given function to the current and given values,
249      * returning the previous value. The function should be
250      * side-effect-free, since it may be re-applied when attempted
251      * updates fail due to contention among threads.  The function
252      * is applied with the current value as its first argument,
253      * and the given update as the second argument.
254      *
255      * @param x the update value
256      * @param accumulatorFunction a side-effect-free function of two arguments
257      * @return the previous value
258      * @since 1.8
259      */
260     public final int getAndAccumulate(int x,
261                                       IntBinaryOperator accumulatorFunction) {
262         int prev, next;
263         do {
264             prev = get();
265             next = accumulatorFunction.applyAsInt(prev, x);
266         } while (!compareAndSet(prev, next));
267         return prev;
268     }
269 
270     /**
271      * Atomically updates the current value with the results of
272      * applying the given function to the current and given values,
273      * returning the updated value. The function should be
274      * side-effect-free, since it may be re-applied when attempted
275      * updates fail due to contention among threads.  The function
276      * is applied with the current value as its first argument,
277      * and the given update as the second argument.
278      *
279      * @param x the update value
280      * @param accumulatorFunction a side-effect-free function of two arguments
281      * @return the updated value
282      * @since 1.8
283      */
284     public final int accumulateAndGet(int x,
285                                       IntBinaryOperator accumulatorFunction) {
286         int prev, next;
287         do {
288             prev = get();
289             next = accumulatorFunction.applyAsInt(prev, x);
290         } while (!compareAndSet(prev, next));
291         return next;
292     }
293 
294     /**
295      * Returns the String representation of the current value.
296      * @return the String representation of the current value
297      */
298     public String toString() {
299         return Integer.toString(get());
300     }
301 
302     /**
303      * Returns the value of this {@code AtomicInteger} as an {@code int}.
304      */
305     public int intValue() {
306         return get();
307     }
308 
309     /**
310      * Returns the value of this {@code AtomicInteger} as a {@code long}
311      * after a widening primitive conversion.
312      * @jls 5.1.2 Widening Primitive Conversions
313      */
314     public long longValue() {
315         return (long)get();
316     }
317 
318     /**
319      * Returns the value of this {@code AtomicInteger} as a {@code float}
320      * after a widening primitive conversion.
321      * @jls 5.1.2 Widening Primitive Conversions
322      */
323     public float floatValue() {
324         return (float)get();
325     }
326 
327     /**
328      * Returns the value of this {@code AtomicInteger} as a {@code double}
329      * after a widening primitive conversion.
330      * @jls 5.1.2 Widening Primitive Conversions
331      */
332     public double doubleValue() {
333         return (double)get();
334     }
335 
336 }