java并发AtomicIntegerArray
Posted juncaif
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java并发AtomicIntegerArray相关的知识,希望对你有一定的参考价值。
java并发AtomicIntegerArray
AtomicIntegerArray的原子性
AtomicIntegerArray的原子性是对数组的元素的,不是数组。
源码基于openjdk 1.8
/*
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
/*
*
*
*
*
*
* Written by Doug Lea with assistance from members of JCP JSR-166
* Expert Group and released to the public domain, as explained at
* http://creativecommons.org/publicdomain/zero/1.0/
*/
package java.util.concurrent.atomic;
import java.util.function.IntUnaryOperator;
import java.util.function.IntBinaryOperator;
import sun.misc.Unsafe;
/**
* An @code int array in which elements may be updated atomically.
* See the @link java.util.concurrent.atomic package
* specification for description of the properties of atomic
* variables.
* @since 1.5
* @author Doug Lea
*/
public class AtomicIntegerArray implements java.io.Serializable
private static final long serialVersionUID = 2862133569453604235L;
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final int base = unsafe.arrayBaseOffset(int[].class);
private static final int shift;
private final int[] array;
static
int scale = unsafe.arrayIndexScale(int[].class);
if ((scale & (scale - 1)) != 0)
throw new Error("data type scale not a power of two");
shift = 31 - Integer.numberOfLeadingZeros(scale);
private long checkedByteOffset(int i)
if (i < 0 || i >= array.length)
throw new IndexOutOfBoundsException("index " + i);
return byteOffset(i);
private static long byteOffset(int i)
return ((long) i << shift) + base;
/**
* Creates a new AtomicIntegerArray of the given length, with all
* elements initially zero.
*
* @param length the length of the array
*/
public AtomicIntegerArray(int length)
array = new int[length];
/**
* Creates a new AtomicIntegerArray with the same length as, and
* all elements copied from, the given array.
*
* @param array the array to copy elements from
* @throws NullPointerException if array is null
*/
public AtomicIntegerArray(int[] array)
// Visibility guaranteed by final field guarantees
this.array = array.clone();
/**
* Returns the length of the array.
*
* @return the length of the array
*/
public final int length()
return array.length;
/**
* Gets the current value at position @code i.
*
* @param i the index
* @return the current value
*/
public final int get(int i)
return getRaw(checkedByteOffset(i));
private int getRaw(long offset)
return unsafe.getIntVolatile(array, offset);
/**
* Sets the element at position @code i to the given value.
*
* @param i the index
* @param newValue the new value
*/
public final void set(int i, int newValue)
unsafe.putIntVolatile(array, checkedByteOffset(i), newValue);
/**
* Eventually sets the element at position @code i to the given value.
*
* @param i the index
* @param newValue the new value
* @since 1.6
*/
public final void lazySet(int i, int newValue)
unsafe.putOrderedInt(array, checkedByteOffset(i), newValue);
/**
* Atomically sets the element at position @code i to the given
* value and returns the old value.
*
* @param i the index
* @param newValue the new value
* @return the previous value
*/
public final int getAndSet(int i, int newValue)
return unsafe.getAndSetInt(array, checkedByteOffset(i), newValue);
/**
* Atomically sets the element at position @code i to the given
* updated value if the current value @code == the expected value.
*
* @param i the index
* @param expect the expected value
* @param update the new value
* @return @code true if successful. False return indicates that
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(int i, int expect, int update)
return compareAndSetRaw(checkedByteOffset(i), expect, update);
private boolean compareAndSetRaw(long offset, int expect, int update)
return unsafe.compareAndSwapInt(array, offset, expect, update);
/**
* Atomically sets the element at position @code i to the given
* updated value if the current value @code == the expected value.
*
* <p><a href="package-summary.html#weakCompareAndSet">May fail
* spuriously and does not provide ordering guarantees</a>, so is
* only rarely an appropriate alternative to @code compareAndSet.
*
* @param i the index
* @param expect the expected value
* @param update the new value
* @return @code true if successful
*/
public final boolean weakCompareAndSet(int i, int expect, int update)
return compareAndSet(i, expect, update);
/**
* Atomically increments by one the element at index @code i.
*
* @param i the index
* @return the previous value
*/
public final int getAndIncrement(int i)
return getAndAdd(i, 1);
/**
* Atomically decrements by one the element at index @code i.
*
* @param i the index
* @return the previous value
*/
public final int getAndDecrement(int i)
return getAndAdd(i, -1);
/**
* Atomically adds the given value to the element at index @code i.
*
* @param i the index
* @param delta the value to add
* @return the previous value
*/
public final int getAndAdd(int i, int delta)
return unsafe.getAndAddInt(array, checkedByteOffset(i), delta);
/**
* Atomically increments by one the element at index @code i.
*
* @param i the index
* @return the updated value
*/
public final int incrementAndGet(int i)
return getAndAdd(i, 1) + 1;
/**
* Atomically decrements by one the element at index @code i.
*
* @param i the index
* @return the updated value
*/
public final int decrementAndGet(int i)
return getAndAdd(i, -1) - 1;
/**
* Atomically adds the given value to the element at index @code i.
*
* @param i the index
* @param delta the value to add
* @return the updated value
*/
public final int addAndGet(int i, int delta)
return getAndAdd(i, delta) + delta;
/**
* Atomically updates the element at index @code i with the results
* of applying the given function, returning the previous value. The
* function should be side-effect-free, since it may be re-applied
* when attempted updates fail due to contention among threads.
*
* @param i the index
* @param updateFunction a side-effect-free function
* @return the previous value
* @since 1.8
*/
public final int getAndUpdate(int i, IntUnaryOperator updateFunction)
long offset = checkedByteOffset(i);
int prev, next;
do
prev = getRaw(offset);
next = updateFunction.applyAsInt(prev);
while (!compareAndSetRaw(offset, prev, next));
return prev;
/**
* Atomically updates the element at index @code i with the results
* of applying the given function, returning the updated value. The
* function should be side-effect-free, since it may be re-applied
* when attempted updates fail due to contention among threads.
*
* @param i the index
* @param updateFunction a side-effect-free function
* @return the updated value
* @since 1.8
*/
public final int updateAndGet(int i, IntUnaryOperator updateFunction)
long offset = checkedByteOffset(i);
int prev, next;
do
prev = getRaw(offset);
next = updateFunction.applyAsInt(prev);
while (!compareAndSetRaw(offset, prev, next));
return next;
/**
* Atomically updates the element at index @code i with the
* results of applying the given function to the current and
* given values, returning the previous value. The function should
* be side-effect-free, since it may be re-applied when attempted
* updates fail due to contention among threads. The function is
* applied with the current value at index @code i as its first
* argument, and the given update as the second argument.
*
* @param i the index
* @param x the update value
* @param accumulatorFunction a side-effect-free function of two arguments
* @return the previous value
* @since 1.8
*/
public final int getAndAccumulate(int i, int x,
IntBinaryOperator accumulatorFunction)
long offset = checkedByteOffset(i);
int prev, next;
do
prev = getRaw(offset);
next = accumulatorFunction.applyAsInt(prev, x);
while (!compareAndSetRaw(offset, prev, next));
return prev;
/**
* Atomically updates the element at index @code i with the
* results of applying the given function to the current and
* given values, returning the updated value. The function should
* be side-effect-free, since it may be re-applied when attempted
* updates fail due to contention among threads. The function is
* applied with the current value at index @code i as its first
* argument, and the given update as the second argument.
*
* @param i the index
* @param x the update value
* @param accumulatorFunction a side-effect-free function of two arguments
* @return the updated value
* @since 1.8
*/
public final int accumulateAndGet(int i, int x,
IntBinaryOperator accumulatorFunction)
long offset = checkedByteOffset(i);
int prev, next;
do
prev = getRaw(offset);
next = accumulatorFunction.applyAsInt(prev, x);
while (!compareAndSetRaw(offset, prev, next));
return next;
/**
* Returns the String representation of the current values of array.
* @return the String representation of the current values of array
*/
public String toString()
int iMax = array.length - 1;
if (iMax == -1)
return "[]";
StringBuilder b = new StringBuilder();
b.append('[');
for (int i = 0; ; i++)
b.append(getRaw(byteOffset(i)));
if (i == iMax)
return b.append(']').toString();
b.append(',').append(' ');
AtomicIntegerArray方法测试
package javalearn.javabase.thread.atomic;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.atomic.AtomicIntegerArray;
@Slf4j
public class AtomicIntegerArrTest
public static void main(String[] args)
int [] arr1 = new int[]10,20,30,40;
AtomicIntegerArray integerArray =new AtomicIntegerArray(arr1);
for(int i= 0;i<arr1.length;i++)
log.info("init arr [] is ",i,integerArray.get(i));
log.info("decrementAndGet arr[] is ",i,integerArray.decrementAndGet(i));
log.info("getAndIncrement arr[] is ",i,integerArray.getAndIncrement(i));
log.info("compareAndSet arr[] is ",i,integerArray.compareAndSet(i,10,100));
log.info("addAndGet 5 arr[] is ",i,integerArray.addAndGet(i,5));
测试结果
12:39:09.205 [main] INFO javalearn.javabase.thread.atomic.AtomicIntegerArrTest - init arr [0] is 10
12:39:09.216 [main] INFO javalearn.javabase.thread.atomic.AtomicIntegerArrTest - decrementAndGet arr[0] is 9
12:39:09.216 [main] INFO javalearn.javabase.thread.atomic.AtomicIntegerArrTest - getAndIncrement arr[0] is 9
12:39:09.216 [main] INFO javalearn.javabase.thread.atomic.AtomicIntegerArrTest - compareAndSet arr[0] is true
12:39:09.216 [main] INFO javalearn.javabase.thread.atomic.AtomicIntegerArrTest - addAndGet 5 arr[0] is 105
12:39:09.216 [main] INFO javalearn.javabase.thread.atomic.AtomicIntegerArrTest - init arr [1] is 20
12:39:09.216 [main] INFO javalearn.javabase.thread.atomic.AtomicIntegerArrTest - decrementAndGet arr[1] is 19
12:39:09.216 [main] INFO javalearn.javabase.thread.atomic.AtomicIntegerArrTest - getAndIncrement arr[1] is 19
12:39:09.216 [main] INFO javalearn.javabase.thread.atomic.AtomicIntegerArrTest - compareAndSet arr[1] is false
12:39:09.216 [main] INFO javalearn.javabase.thread.atomic.AtomicIntegerArrTest - addAndGet 5 arr[1] is 25
12:39:09.216 [main] INFO javalearn.javabase.thread.atomic.AtomicIntegerArrTest - init arr [2] is 30
12:39:09.216 [main] INFO javalearn.javabase.thread.atomic.AtomicIntegerArrTest - decrementAndGet arr[2] is 29
12:39:09.216 [main] INFO javalearn.javabase.thread.atomic.AtomicIntegerArrTest - getAndIncrement arr[2] is 29
12:39:09.216 [main] INFO javalearn.javabase.thread.atomic.AtomicIntegerArrTest - compareAndSet arr[2] is false
12:39:09.216 [main] INFO javalearn.javabase.thread.atomic.AtomicIntegerArrTest - addAndGet 5 arr[2] is 35
12:39:09.217 [main] INFO javalearn.javabase.thread.atomic.AtomicIntegerArrTest - init arr [3] is 40
12:39:09.217 [main] INFO javalearn.javabase.thread.atomic.AtomicIntegerArrTest - decrementAndGet arr[3] is 39
12:39:09.217 [main] INFO javalearn.javabase.thread.atomic.AtomicIntegerArrTest - getAndIncrement arr[3] is 39
12:39:09.217 [main] INFO javalearn.javabase.thread.atomic.AtomicIntegerArrTest - compareAndSet arr[3] is false
12:39:09.217 [main] INFO javalearn.javabase.thread.atomic.AtomicIntegerArrTest - addAndGet 5 arr[3] is 45
以上是关于java并发AtomicIntegerArray的主要内容,如果未能解决你的问题,请参考以下文章