在计算机科学中,比较和交换(Conmpare And Swap)是用于实现多线程同步的原子指令。 它将内存位置的内容与给定值进行比较,只有在相同的情况下,将该内存位置的内容修改为新的给定值。 这是作为单个原子操作完成的。 原子性保证新值基于最新信息计算; 如果该值在同一时间被另一个线程更新,则写入将失败。 操作结果必须说明是否进行替换; 这可以通过一个简单的布尔响应(这个变体通常称为比较和设置),或通过返回从内存位置读取的值来完成(摘自维基本科)
CAS可以有效的提升并发的效率,但同时也会引入ABA问题。
CAS其实就是实现一种乐观的自旋锁,相较于synchronize的悲观锁,没有阻塞状态,自然也就没有上下文的切换了,而线程状态的切换,耗时比CAS的自旋比较操作耗时大得多。
原子性是什么?
原子性就是最小单位,原子性操作就是最小的操作,无法再进一步分割,这操作的结果只有2种,完成或者未完成。
例如 int a = 1,这种就是原子性操作。
而a++,这个就不是原子性操作,因为a++,会拆解为3步,读取a的值,a增加1,再把a的值刷新。
还是那个例子,2个线程,同时对一个变量a进行递增,每次+1,递增100次。当2个线程都执行完毕,a的结果不会是200,会小于200。
解决办法?
第一时间就会想到加个锁,因为锁能保证一段代码块执行完毕,从而保证原子性。
但是,如果要执行的代码足够简单的时候,例如上面的只有个a++,使用锁的话,会十分浪费,性能也不高,因为一个线程获得了锁,其他线程都无法进行了。
所以,就需要用到了CAS
怎样工作的:
初始AtomicInteger的值为0
线程A执行:var5 = this.getIntVolatile(var1,var2);获取的结果为:0
线程A被暂停
线程B执行:var5 = this.getIntVolatile(var1,var2);获取的结果为:0
线程B执行:this.compareAndSwapInt(var1,var2,var5,var5 + var4)
线程B成功将AtomicInteger中的值改为1
线程A恢复运行,执行:this.compareAndSwapInt(var1,var2,var5,var5 + var4),此时线程A使用var1和var2从AtomicInteger中获取的值为:1,而传入的var5为0,比较失败,返回false,继续循环。
线程A执行:var5 = this.getIntVolatile(var1,var2);获取的结果为:1
线程A执行:this.compareAndSwapInt(var1,var2,var5,var5 + var4),此时线程A使用var1和var2从AtomicInteger中获取的值为:1,而传入的var5为1,比较成功,将其修改为var5 + var4,也就是2,将AtomicInteger中的值改为2,结束。