0%

CAS

文章字数:287,阅读全文大约需要1分钟

CAS(Compare-and-Swap),比较并替换。java并发包中很多类都采用了CAS技术,当获取到的内存地址和期待的内存地址相等时才将值修改,否则将或获取到的新地址变成期望地址,并循环进行下一次判断,直到成功赋值。保证代码的原子性。

使用例子

1
2
3
4
private static AtomicInteger race = new AtomicInteger(0);
public static void increase(){
race.getAndIncrement();//原子操作,race++
}

CAS缺点

  • 循环时间开销可能会很大
  • 只能保证一个共享变量进行原子操作
  • ABA问题:一个变量在读取时是A,准备赋值时检测也是A。但是可能是从A变成B,又从B变成了A,发生过变化。
    带有标记的引用类AtomicStampedReference可以通过控制变量的版本来保证CAS的正确

AtomicStampedReference

  1. 循环1-1000
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public class test1 {
    private static AtomicStampedReference<Integer> integer = new AtomicStampedReference<>(0,0);
    public static void main(String[] args) {
    for(int i=0;i<1000;i++){
    final int timeStamp = integer.getStamp();
    new Thread(){
    @Override
    public void run() {
    System.out.println("timeStamp = " + timeStamp);
    while (true){
    if(integer.compareAndSet(integer.getReference(),integer.getReference()+1,timeStamp,timeStamp+1)){
    break;
    }
    }
    }
    }.run();
    }
    }
    }
  • integer.getStamp();获取版本号
  • compareAndSet(预期对象,修改后,预期版本,修改后版本)返回成功或失败,失败应该手动进入循环直到完成替换。