21原子类

无锁工具类的典范

实现

硬件支持CAS指令,作为一条CPU指令本身能保证原子性

原子类与锁比较

加解锁本身消耗性能,获取不到锁的线程会阻塞出发线程切换,线程切换也消耗性能。
原子类无锁

ABA问题

解决:版本号,每次改变版本号自增,同时修改值时检查版本号
AtomicStampedReference
AtomicMarkableReference (boolean类型版本号)

原子类分类

  • 原子化基础数据类型
  • 原子化的对象引用类型
  • 原子化数组
  • 原子化对象属性更新器
  • 原子化的累加器

基础数据类型

AtomicBoolean、AtomicInteger、AtomicLong
相关方法类似

1
2
3
4
5
6
7
8
9
10
11
12
getAndIncrement()	//	原⼦化	i++
getAndDecrement() // 原⼦化的 i--
incrementAndGet() // 原⼦化的 ++i
decrementAndGet() // 原⼦化的 --i
getAndAdd(delta) // 当前值 +=delta,返回 += 前的值
addAndGet(delta) // 当前值 +=delta,返回 += 后的值
compareAndSet(expect,update) //CAS 操作,返回是否成功
//以下四个⽅法 新值可以通过传⼊func函数来计算
getAndUpdate(func)
updateAndGet(func)
getAndAccumulate(x,func)
accumulateAndGet(x,func)

对象引用类型

AtomicReference、AtomicStampedReference、AtomicMarkableReference

AtomicStampedReference实现的CAS方法就增加了版本号参数

1
2
3
4
5
boolean compareAndSet(
V expectedReference,
V newReference,
int expectedStamp,
int newStamp)

AtomicMarkableReference将版本号简化成了一个Boolean值

1
2
3
4
5
boolean compareAndSet(
V expectedReference,
V newReference,
boolean expectedMark,
boolean newMark)

数组

AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray

对象属性更新器

AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater
可以原子化地更新对象的属性,对象属性必须是volatile类型,只有这样才能保证可见性;反
射机制实现

累加器

DoubleAccumulator、DoubleAdder、LongAccumulator、LongAdder
仅执行累加操作,相比原子化的基本数据类型,速度更快,不支持compareAndSet方法
若只需要累加操作,使用原子化的累加器性能会更好

总结

相对于互斥锁方案性能好,不会死锁(但会饥饿、活锁,自旋重试)
只针对一个共享变量,对于多共享变量使用互斥锁