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
7 package java.util.concurrent.atomic;
8 import sun.misc.Unsafe;
12 * An <tt>int</tt> array in which elements may be updated atomically.
13 * See the {@link java.util.concurrent.atomic} package
14 * specification for description of the properties of atomic
19 public class AtomicIntegerArray implements java.io.Serializable {
20 private static final long serialVersionUID = 2862133569453604235L;
22 // setup to use Unsafe.compareAndSwapInt for updates
23 private static final Unsafe unsafe = Unsafe.getUnsafe();
24 private static final int base = unsafe.arrayBaseOffset(int[].class);
25 private static final int scale = unsafe.arrayIndexScale(int[].class);
26 private final int[] array;
28 private long rawIndex(int i) {
29 if (i < 0 || i >= array.length)
30 throw new IndexOutOfBoundsException("index " + i);
31 return base + i * scale;
35 * Creates a new AtomicIntegerArray of given length.
37 * @param length the length of the array
39 public AtomicIntegerArray(int length) {
40 array = new int[length];
41 // must perform at least one volatile write to conform to JMM
43 unsafe.putIntVolatile(array, rawIndex(0), 0);
47 * Creates a new AtomicIntegerArray with the same length as, and
48 * all elements copied from, the given array.
50 * @param array the array to copy elements from
51 * @throws NullPointerException if array is null
53 public AtomicIntegerArray(int[] array) {
55 throw new NullPointerException();
56 int length = array.length;
57 this.array = new int[length];
60 for (int i = 0; i < last; ++i)
61 this.array[i] = array[i];
62 // Do the last write as volatile
63 unsafe.putIntVolatile(this.array, rawIndex(last), array[last]);
68 * Returns the length of the array.
70 * @return the length of the array
72 public final int length() {
77 * Gets the current value at position <tt>i</tt>.
80 * @return the current value
82 public final int get(int i) {
83 return unsafe.getIntVolatile(array, rawIndex(i));
87 * Sets the element at position <tt>i</tt> to the given value.
90 * @param newValue the new value
92 public final void set(int i, int newValue) {
93 unsafe.putIntVolatile(array, rawIndex(i), newValue);
97 * Eventually sets the element at position <tt>i</tt> to the given value.
100 * @param newValue the new value
103 public final void lazySet(int i, int newValue) {
104 unsafe.putOrderedInt(array, rawIndex(i), newValue);
108 * Atomically sets the element at position <tt>i</tt> to the given
109 * value and returns the old value.
112 * @param newValue the new value
113 * @return the previous value
115 public final int getAndSet(int i, int newValue) {
117 int current = get(i);
118 if (compareAndSet(i, current, newValue))
124 * Atomically sets the element at position <tt>i</tt> to the given
125 * updated value if the current value <tt>==</tt> the expected value.
128 * @param expect the expected value
129 * @param update the new value
130 * @return true if successful. False return indicates that
131 * the actual value was not equal to the expected value.
133 public final boolean compareAndSet(int i, int expect, int update) {
134 return unsafe.compareAndSwapInt(array, rawIndex(i),
139 * Atomically sets the element at position <tt>i</tt> to the given
140 * updated value if the current value <tt>==</tt> the expected value.
141 * May fail spuriously and does not provide ordering guarantees,
142 * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
145 * @param expect the expected value
146 * @param update the new value
147 * @return true if successful.
149 public final boolean weakCompareAndSet(int i, int expect, int update) {
150 return compareAndSet(i, expect, update);
154 * Atomically increments by one the element at index <tt>i</tt>.
157 * @return the previous value
159 public final int getAndIncrement(int i) {
161 int current = get(i);
162 int next = current + 1;
163 if (compareAndSet(i, current, next))
169 * Atomically decrements by one the element at index <tt>i</tt>.
172 * @return the previous value
174 public final int getAndDecrement(int i) {
176 int current = get(i);
177 int next = current - 1;
178 if (compareAndSet(i, current, next))
184 * Atomically adds the given value to the element at index <tt>i</tt>.
187 * @param delta the value to add
188 * @return the previous value
190 public final int getAndAdd(int i, int delta) {
192 int current = get(i);
193 int next = current + delta;
194 if (compareAndSet(i, current, next))
200 * Atomically increments by one the element at index <tt>i</tt>.
203 * @return the updated value
205 public final int incrementAndGet(int i) {
207 int current = get(i);
208 int next = current + 1;
209 if (compareAndSet(i, current, next))
215 * Atomically decrements by one the element at index <tt>i</tt>.
218 * @return the updated value
220 public final int decrementAndGet(int i) {
222 int current = get(i);
223 int next = current - 1;
224 if (compareAndSet(i, current, next))
230 * Atomically adds the given value to the element at index <tt>i</tt>.
233 * @param delta the value to add
234 * @return the updated value
236 public final int addAndGet(int i, int delta) {
238 int current = get(i);
239 int next = current + delta;
240 if (compareAndSet(i, current, next))
246 * Returns the String representation of the current values of array.
247 * @return the String representation of the current values of array.
249 public String toString() {
250 if (array.length > 0) // force volatile read
252 return Arrays.toString(array);