§1 总览
原子类大多在包 java.util.concurrent.atomic 下
原子型 | 基础型 | 类型 | 说明 |
---|---|---|---|
AtomicBoolean | boolean | 基本 | |
AtomicInteger | int | 基本 | |
AtomicIntegerArray | int[] | 数组 | |
AtomicIntegerFieldUpdater | |||
AtomicLong | long | 基本 | |
AtomicLongArray | long[] | 数组 | |
AtomicLongFieldUpdater | |||
AtomicMarkableReference | |||
AtomicReference | Object | 引用 | |
AtomicReferenceArray | Object[] | 数组 | |
AtomicReferenceFieldUpdater | |||
AtomicStampedReference | |||
DoubleAccumulator | |||
DoubleAdder | |||
LongAccumulator | |||
LongAdder |
通用 api
get()
获取getAndSet()
获取并赋予新值,相当于i=x
getAndIncrement()
获取并自增,相当于i++
getAndDecrement()
获取并自减,相当于i--
getAndAdd()
获取并在原值基础上 + 差值,相当于i+=x
compareAndSet()
比较,如果相等就赋予新值
§2 基本类型原子类
基础数据类型原子类
- AtomicBoolean,相当于 boolean
- AtomicInteger,相当于 int
- AtomicLong,相当于 long
示例
AtomicInteger atomicInteger = new AtomicInteger(10);
atomicInteger.getAndIncrement();//相当于 i++
§3 数组类型原子类
数组数据类型原子类
类似 基础数据类型原子类
- AtomicBooleanArray,相当于 boolean[]
- AtomicIntegerArray,相当于 int[]
- AtomicLongArray,相当于 long[]
§4 引用类型原子类
引用类型原子类
AtomicReference
相当于 Object
常用于实现基于线程的自旋锁
不能处理 ABA 问题AtomicStamptReference
在AtomicReference
增加了版本信息
常用于实现基于线程的自旋锁
可以处理 ABA 问题AtomicMarkableReference
在AtomicReference
增加了修改标记
修改值前,应判断修改标记isMarked()
修改值时,应同步修改 修改标记 ,compareAndSet(old, new, oldMark, !oldMark)
可以处理 ABA 问题,相对于AtomicStamptReference
只关心是否被改过,而不关心更改次数
注意
引用类型原子类只能 CAS 引用本身,而不是引用内部的字段值
User user = new User();
AtomicReference<User> atomicUser = new AtomicReference<>();
atomicUser.set(user);
atomicUser.compareAndSet(user,new User());
§4 属性修改原子类
- 用于对非线程安全的字段进行 线程安全 的修改
- 基于反射实现
- 被修改的字段必须被
public volatile
修饰
包含下面三个类
- AtomicIntegerFieldUpdater
- AtomicLongFieldUpdater
- AtomicReferenceFieldUpdater
AtomicIntegerFieldUpdater<User> updater =
AtomicIntegerFieldUpdater.newUpdater(User.class,"age");
updater.getAndIncrement(user);
§5 原子操作增强
- DoublAccumulator
- DoubleAdder
- LongAccumulator
- LongAdder
应用场景
适用于不要求实时精确,的基础数据累加
- 点赞计数器
- int[] 所有元素 ++
与 AtomicLong
比较
- 高并发场景下性能提高,减少 cas 消耗(大约一个数量级)
- 不能保证实时精准
LongAdder
和 LongAccumulator
的区别
初始值 | 加值 | |
---|---|---|
LongAdder | 只能是 0 | 只能是 1 |
LongAccumulator | 任意 | 任意 |
LongAdder adder = new LongAdder();
adder.increment();
adder.increment();
System.out.println(adder.sum()); // 2
LongAccumulator accumulator = new LongAccumulator((x,y)->x+y,0);
accumulator.accumulate(1);
accumulator.accumulate(2);
System.out.println(accumulator.get()); // 3
源码
详见 基础 | 并发编程 - [Striped64]
§6 原子操作底层类
- Number
- Striped64
详见 基础 | 并发编程 - [Striped64]