CAS操作与原子操作类

1.CAS的实现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.CAS的特点

CAS操作最好发生在,

3. 原子更新基本类型

atomic 包提高原子更新基本类型的工具类,主要有这些:

AtomicBoolean:以原子更新的方式更新 boolean;
**AtomicInteger:**以原子更新的方式更新 Integer;
AtomicLong:以原子更新的方式更新 Long;

这里以 AtomicInteger 为例总结常用的方法
1.incrementAndGet() :以原子的方式将实例中的原值进行加 1 操作,并返回最终相加后的结果;
2.getAndIncrement():以原子的方式将实例中的原值加 1,返回的是自增前的旧值;
3.addAndGet(int delta) :以原子方式将输入的数值与实例中原本的值相加,并返回最后的结果;
4.getAndSet(int newValue):将实例中的值更新为新值,并返回旧值;

4. 原子引用

AtomicReference:原子更新引用类型;

主线程仅能判断出共享变量的值与最初值 A 是否相同,不能感知到这种从 A 改为 B 又 改回 A 的情况,如果主线程希望:只要有其它线程【动过了】共享变量,那么自己的 cas 就算失败,这时,仅比较值是不够的,需要再加一个版本号;
AtomicMarkableReference:原子更新引用类型,这种更新方式会带有版本号。而为什么在更新的时候会带有版本号,是为了解决 CAS 的 ABA 问题;

AtomicStampedReference 可以给原子引用加上版本号,追踪原子引用整个的变化过程,如: A -> B -> A ->C ,通过AtomicStampedReference,我们可以知道,引用变量中途被更改了几次。但是有时候,并不关心引用变量更改了几次,只是单纯的关心是否更改过,所以就有了

AtomicStampedReference:原子更新引用类型,这种更新方式会带有boolean值,是为了解决 CAS 的引用变量是否被更改的问题;

5. 原子数组

AtomicIntegerArray
AtomicLongArray
AtomicReferenceArray

demo(
  ()-> new AtomicIntegerArray(10),
  (array) -> array.length(),
  (array, index) -> array.getAndIncrement(index),
  array -> System.out.println(array)
);

6. 字段更新器

AtomicReferenceFieldUpdater // 域 字段
AtomicIntegerFieldUpdater
AtomicLongFieldUpdater
利用字段更新器,可以针对对象的某个域(Field)进行原子操作,只能配合 volatile 修饰的字段使用,否则会出现异常

public class Test5 {
   private volatile int field;
   public static void main(String[] args) {
   AtomicIntegerFieldUpdater fieldUpdater =
AtomicIntegerFieldUpdater.newUpdater(Test5.class, "field");
   Test5 test5 = new Test5();
   fieldUpdater.compareAndSet(test5, 0, 10);
   // 修改成功 field = 10
   System.out.println(test5.field);
   // 修改成功 field = 20
   fieldUpdater.compareAndSet(test5, 10, 20);
   System.out.println(test5.field);
   // 修改失败 field = 20
   fieldUpdater.compareAndSet(test5, 10, 30);
   System.out.println(test5.field);
 }
}

7. 原子累加器

比较 AtomicLong 与 LongAdder

for (int i = 0; i < 5; i++) {
 demo(() -> new LongAdder(), adder -> adder.increment());
}
for (int i = 0; i < 5; i++) {
 demo(() -> new AtomicLong(), adder -> adder.getAndIncrement());
}

LongAdder性能更强,原因很简单,就是在有竞争时,设置多个累加单元,Therad-0 累加 Cell[0],而 Thread-1 累加Cell[1]… 最后将结果汇总。这样它们在累加时操作的不同的 Cell 变量,因此减少了 CAS 重试失败,从而提高性能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值