CAS

CAS:compareAndSet(比较并设置)
底层是lock cmpxchg指令(X86架构),在单核CPU和多核CPU下都能保证比较-交换的原子性
在多核状态下,某个核执行到带lock的指令时,CPU会让总线锁住,当这个核把此指令执行完毕,在开启总线,这个过程中不会被线程的调度机制所打断,保证了多个线程对内存操作的准确性,是原子的

CAS保存的变量用volatile修饰,保证变量可见性

为什么无锁效率更高

无锁情况下,即使重试失败,线程始终告诉运行,没有停歇,而synchronized会让线程在没有获得锁的时候,发生上下文切换,进入阻塞

CAS特点

结合CAS和volatile可以实现无锁并发,适用于线程数少,多核CPU的场景下

  • CAS是基于乐观锁的思想:最乐观的估计,不怕别的线程来修改共享变量,我重试就行
  • synchronized是基于悲观锁的思想,最悲观的估计,得防着其他线程修改共享变量,一次只能一个人进入临界区
  • CAS体现的是无锁并发、无阻塞并发
    • 因为没有使用synchronized,所以线程不会陷入阻塞,这是效率提升的因素之一
    • 但如果竞争激烈,可以想到重试必然频繁发生,效率会受到影响

原子整数

JUC并发包提供了:

  • AtomicBoolean
  • AtomicInteger
  • AtomicLong

compareAndSet(expect,update):比较并赋值

加法

incrementAndGet():自增并获取值
getAndIncrement():获取并自增
getAndAdd(data):获取并增加
addAndGet(data):增加并获取

复杂运算

updateAndGet(函数式接口(传入初始值,返回设置值))
getAndUpdate(函数式接口(传入初始值,返回设置值))

原子引用类型

  • AtomicReference
  • AtomicMarkableReference
  • AtomicStampedReference

atomicReference:通过比较对象地址判断共享对象是否改变
会有ABA问题

AtomicStampedReference:通过版本号判断共享对象是否改变(只有版本号和对象都没有改变更改)
解决ABA问题

AtomicMarkableReference:有时候我们并不关心引用变量更改了几次,只是单纯关心是否被更改过

如果你需要记录修改了多少次(防止任何形式的重叠),请使用 AtomicStampedReference,并配合自增的 int 版本号。

如果你只需要一个二元状态标记(比如:这封邮件是否已被读取?这个节点是否已被标记删除?),才使用 AtomicMarkableReference。

原子数组

  • AtomicIntegerArray
  • AtomicLongArray
  • AtomicReferenceArray

字段更新器

  • AtomicRefrerenceFieldUpdater //字段
  • AtomicIntegerFieldUpdater
  • AtomicLongFieldUpdate

创建:AtomicReferenceFieldUpdater.newUpdater(类名,属性类型,属性名)
注意:字段一定加volatile修饰

原子累加器

  • LongAccumulator
  • LongAdder

相比AtomicInteger、AtomicLong性能更好
原因:有竞争时,设置多个累加单元,Thread-0累加cell[0],而Thread-1累加cell[1]…最后将结果汇总,这样他们在累加时操作的不同cell变量,因此减少了CAS重试失败,从而提高性能

伪共享:一个缓存行(64字节)放入多条数据

@Contended注解(防止伪共享),通过加入padding,使数据放入不同缓存行,避免不相关数据之间的修改导致频繁地缓存失效

LongAdder 中 cell 的创建与使用流程:

  • 先尝试对 base 做 CAS,成功直接返回
  • 若失败,进入 cells 逻辑(longAccumulate)
  • 若 cells 未初始化,尝试通过 CAS 获取锁并创建 cells 数组(初始长度为2)
  • 若 cells 已存在:
    • 根据线程 probe 定位 cell
    • 若 cell 存在,CAS 更新
    • 若不存在,尝试创建 cell(需加锁)
  • 若 CAS 冲突:
    • 若 cells 长度小于 CPU 核数,尝试扩容
    • 否则通过 rehash 更换槽位,减少冲突
  • 整个过程在自旋中完成,直到成功更新

Unsafe

提供了非常底层的,操作内存、线程的方法

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐