在计算机科学中,比较和交换(Conmpare And Swap)是用于实现多线程同步的原子指令。 它将内存位置的内容与给定值进行比较,只有在相同的情况下,将该内存位置的内容修改为新的给定值。 这是作为单个原子操作完成的。 原子性保证新值基于最新信息计算; 如果该值在同一时间被另一个线程更新,则写入将失败。 操作结果必须说明是否进行替换; 这可以通过一个简单的布尔响应(这个变体通常称为比较和设置),或通过返回从内存位置读取的值来完成(摘自维基本科)
下面看代码
AtomicInteger atomicInteger = new AtomicInteger(1);
atomicInteger.getAndIncrement();
atomicInteger.compareAndSet(atomicInteger.getAndIncrement(), 6)
compareAndSet(V,E,U) V是内存的值,E是预期的值,U是要修改的值,通过比较替换实现无锁的操作,其实是乐观锁,不过CAS有一个ABA的问题。
2.ABA问题
比如有2个线程1,2 如果内存中的值为X,1线程从内存中获取到X,并且想设置值为A,线程2也从内存中获取到X,并且线程2先执行设置内存的值为B,然后在设置为X,此时1线程获取到的值X,跟内存中对比的值X结果是一样的,之后线程1就可以设置内存的值为A,此时觉得没什么问题,但是线程2已经修改过这个值了,尽管线程1的操作成功但是不代表没有问题,至于会有什么问题,跟链表有关系,自行baidu吧
解决方案:
java 提供两种解决方案
1。AtomicStampedReference是带时间戳的
AtomicStampedReference atomicStampedReference1 = new AtomicStampedReference(100, stamp);
System.out.println(atomicStampedReference1.compareAndSet(100, 2, stamp+1, stamp+1));
System.out.println(atomicStampedReference1.getReference());
2。是带boolean类型的
AtomicMarkableReference atomicMarkableReference = new AtomicMarkableReference(100,true);
System.out.println(atomicMarkableReference.compareAndSet(100, 4, true, false));
System.out.println(atomicMarkableReference.getReference());
System.out.println(atomicMarkableReference.compareAndSet(100, 4, true, false));