1. AtomicIntegerArray 是什么?
AtomicIntegerArray 就是:
线程安全的
int[]数组。
普通数组:
java
int[] array = new int[10];
而原子数组:
java
AtomicIntegerArray array = new AtomicIntegerArray(10);
区别在于:
int[]
↓
普通数组
↓
多个线程同时修改同一个元素时,不保证原子性
AtomicIntegerArray
↓
原子数组
↓
对元素的修改可以进行原子操作
2. 最基本的创建方式
方式一:指定长度
java
AtomicIntegerArray array = new AtomicIntegerArray(5);
相当于:
下标: 0 1 2 3 4
↓ ↓ ↓ ↓ ↓
[0] [0] [0] [0] [0]
方式二:根据已有数组创建
java
int[] source = {10, 20, 30};
AtomicIntegerArray array =
new AtomicIntegerArray(source);
此时:
index 0 1 2
↓ ↓ ↓
10 20 30
3. 获取元素:get()
java
int value = array.get(0);
意思:
获取下标
0的元素。
例如:
java
AtomicIntegerArray array =
new AtomicIntegerArray(new int[]{10, 20, 30});
System.out.println(array.get(1));
输出:
20
4. 修改元素:set()
java
array.set(0, 100);
意思:
把下标 0 的元素修改成 100。
例如:
原来:
[10, 20, 30]
array.set(0, 100)
变成:
[100, 20, 30]
5. 最重要的:incrementAndGet()
这个你刚才那个 Incrementer 示例里面就用到了。
java
array.incrementAndGet(0);
意思:
把下标 0 的元素原子地 +1,然后返回新值。
例如:
java
AtomicIntegerArray array =
new AtomicIntegerArray(new int[]{10, 20, 30});
int result = array.incrementAndGet(0);
执行:
10 → 11
所以:
result == 11
6. getAndIncrement()
这个和刚才一样,也特别容易搞混。
java
int result = array.getAndIncrement(0);
意思:
先返回旧值,再 +1。
例如:
原来:
10
getAndIncrement()
返回:
10
数组变成:
11
所以:
incrementAndGet()
↓
先 +1,再返回
getAndIncrement()
↓
先返回,再 +1
7. decrementAndGet()
同样:
java
array.decrementAndGet(0);
就是:
下标 0 的元素原子地 -1,并返回新值。
例如:
10 → 9
8. getAndDecrement()
java
int result = array.getAndDecrement(0);
就是:
原来:10
返回:10
然后:
10 → 9
所以和 increment 是完全一样的规律。
9. addAndGet()
这个也很常用。
array.addAndGet(0, 10);
意思:
把下标 0 的元素原子地加 10,并返回新值。
例如:
原来:
[100, 20, 30]
addAndGet(0, 10)
↓
[110, 20, 30]
返回:
110
10. getAndAdd()
java
int result = array.getAndAdd(0, 10);
意思:
先返回旧值,再加 10。
例如:
原来:100
返回:100
然后:
100 → 110
11. 为什么它比 int[] 安全?
这是你学习 AtomicIntegerArray 最重要的地方。
假设:
java
int[] array = {0};
两个线程同时:
java
array[0]++;
本质上还是:
读取
↓
+1
↓
写回
所以可能出现:
线程A读取 0
线程B读取 0
线程A写入 1
线程B写入 1
最终 = 1
而:
java
AtomicIntegerArray array =
new AtomicIntegerArray(1);
两个线程执行:
java
array.incrementAndGet(0);
底层会使用类似 CAS 的原子更新机制。
因此:
线程A:0 → 1
线程B:发现0已经变成1
↓
重新尝试
↓
1 → 2
最终:
2
12. 你现在把它和 AtomicInteger 放一起理解
这个非常重要:
AtomicInteger
↓
原子地操作一个 int
AtomicIntegerArray
↓
原子地操作 int[] 中的某个元素
例如:
java
AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet();
相当于:
java
AtomicIntegerArray array =
new AtomicIntegerArray(10);
array.incrementAndGet(3);
前者操作的是:
一个 int
后者操作的是:
数组下标 3 的 int
你把 AtomicIntegerArray 理解成"AtomicInteger 的数组版",基本就对了。