AtomicIntegerArray类详解
介紹
java.util.concurrent.atomic.AtomicIntegerArray類提供了可以以原子方式讀取和寫入的底層int數組的操作,還包含高級原子操作。 AtomicIntegerArray支持對底層int數組變量的原子操作。 它具有獲取和設置方法,如在變量上的讀取和寫入。 也就是說,一個集合與同一變量上的任何后續get相關聯。 原子compareAndSet方法也具有這些內存一致性功能。
| 1 | public int addAndGet(int i, int delta) | 原子地將給定的值添加到索引i的元素。 |
| 2 | public boolean compareAndSet(int i, int expect, int update) | 如果當前值==期望值,則將位置i處的元素原子設置為給定的更新值。 |
| 3 | public int decrementAndGet(int i) | 索引i處的元素原子并自減1。 |
| 4 | public int get(int i) | 獲取位置i的當前值。 |
| 5 | public int getAndAdd(int i, int delta) | 原子地將給定的值添加到索引i的元素。 |
| 6 | public int getAndDecrement(int i) | 索引i處的元素原子并自減1,并返回舊值。 |
| 7 | public int getAndIncrement(int i) | 將位置i處的元素原子設置為給定值,并返回舊值。 |
| 8 | public int getAndSet(int i, int newValue) | 將位置i處的元素原子設置為給定值,并返回舊值。 |
| 9 | public int incrementAndGet(int i) | 在索引i處以原子方式自增元素。 |
| 10 | public void lazySet(int i, int newValue) | 最終將位置i處的元素設置為給定值。 |
| 11 | public int length() | 返回數組的長度。 |
| 12 | public void set(int i, int newValue) | 將位置i處的元素設置為給定值。 |
| 13 | public String toString() | 返回數組的當前值的String表示形式。 |
| 14 | public boolean weakCompareAndSet(int i, int expect, int update) | 如果當前值==期望值,則將位置i處的元素原子設置為給定的更新值。 |
實例
package main.java.study;
import java.util.concurrent.atomic.AtomicIntegerArray;
public class AtomicIntegerArrayTest {
?? ?static class Increment implements Runnable {
?? ??? ?public void run() {
?? ??? ??? ?for (int i = 0; i < atomicIntegerArray.length(); i++) {
?? ??? ??? ??? ?int add = atomicIntegerArray.incrementAndGet(i);
?? ??? ??? ??? ?System.out.println("Thread " + Thread.currentThread().getId() + ", index " + i + ", value: " + add);
?? ??? ??? ?}
?? ??? ?}
?? ?}
?? ?static class Compare implements Runnable {
?? ??? ?public void run() {
?? ??? ??? ?for (int i = 0; i < atomicIntegerArray.length(); i++) {
?? ??? ??? ??? ?boolean swapped = atomicIntegerArray.compareAndSet(i, 2, 3);
?? ??? ??? ??? ?if (swapped) {
?? ??? ??? ??? ??? ?System.out.println("Thread " + Thread.currentThread().getId() + ", index " + i + ", value: 3");
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ?}
?? ?}
?? ?private static AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(10);
?? ?public static void main(String[] args) throws InterruptedException {
?? ??? ?for (int i = 0; i < atomicIntegerArray.length(); i++) {
?? ??? ??? ?atomicIntegerArray.set(i, 1);
?? ??? ?}
?? ??? ?Thread t1 = new Thread(new Increment());
?? ??? ?Thread t2 = new Thread(new Compare());
?? ??? ?t1.start();
?? ??? ?t2.start();
?? ??? ?t1.join();
?? ??? ?t2.join();
?? ??? ?System.out.println("Values: ");
?? ??? ?for (int i = 0; i < atomicIntegerArray.length(); i++) {
?? ??? ??? ?System.out.print(atomicIntegerArray.get(i) + " ");
?? ??? ?}
?? ?}
}
?
?
結果
Thread 11, index 0, value: 3
Thread 10, index 0, value: 2
Thread 10, index 1, value: 2
Thread 10, index 2, value: 2
Thread 10, index 3, value: 2
Thread 10, index 4, value: 2
Thread 10, index 5, value: 2
Thread 10, index 6, value: 2
Thread 10, index 7, value: 2
Thread 10, index 8, value: 2
Thread 10, index 9, value: 2
Values:
3 2 2 2 2 2 2 2 2 2
源碼
AtomicIntegerArray 的public方法主要是call以下方法
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 {
??????? //獲取數據元素的大小(size),int類型的是 4
??????? int scale = unsafe.arrayIndexScale(int[].class);
??????? if ((scale & (scale - 1)) != 0)
??????????? throw new Error("data type scale not a power of two");
????? //numberOfLeadingZeros:返回無符號整型i的最高非零位前面的0的個數,int類型(4)的前置0個數為29
???? //下面表達式返回位移量,用于計算下標。用于<<操作符,表示乘以2^shift????? 2^2=4
??????? shift = 31 - Integer.numberOfLeadingZeros(scale);
??? }
??? private long checkedByteOffset(int i) {
??????? if (i < 0 || i >= array.length)
??????????? throw new IndexOutOfBoundsException("index " + i);
??????? return byteOffset(i);
??? }
? //計算第i個元素的偏移量.
??? private static long byteOffset(int i) {
??????? return ((long) i << shift) + base;
??? }
??? public AtomicIntegerArray(int length) {
??????? array = new int[length];
??? }
??? public AtomicIntegerArray(int[] array) {
??????? // Visibility guaranteed by final field guarantees
??????? this.array = array.clone();
??? }
??? public final int get(int i) {
??????? return getRaw(checkedByteOffset(i));
??? }
??? private int getRaw(long offset) {
??????? return unsafe.getIntVolatile(array, offset);
??? }
??? public final void set(int i, int newValue) {
??????? unsafe.putIntVolatile(array, checkedByteOffset(i), newValue);
??? }
??? public final void lazySet(int i, int newValue) {
??????? unsafe.putOrderedInt(array, checkedByteOffset(i), newValue);
??? }
}
數組在內存中是連續內存,如下圖:
| 0 | 1 | 2 | …… | …… | n-1 |
?
Java規定數組中的元素都是相同類型,因此數組中的每個元素的內存大小是相同的,也就是說,只要知道數組的起始位置,我們就可以算出指定下標的數組元素的內存位置
pos = base(起始位置) + i(下標) * size(類型大小)
?
總結
以上是生活随笔為你收集整理的AtomicIntegerArray类详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Semaphore应用及原理
- 下一篇: AtomicIntegerFieldUp