高并发(11)-原子操作CAS(Compare And Swap)?
- 前言
- 什么是原子操作
- 如何实现原子操作
-
- CAS的原理是什么
- CAS的问题
-
- ABA问题
- 开销问题
- 只能保证一个共享变量的原子操作?
前言
上篇文章讲解了线程的并发工具类之Semaphore,本文就来讲解下关于原子操作。
来了解下什么原子操作,又如何实现原子操作
什么是原子操作
原子操作就是一个操作或多个操作,要么全部执行成功要么全部执行失败,不会出现一部分成功一部分失败的情况。
经典的例子就是转账,a给b转账100元,a要扣减100,b要增加100,这其中包含了a扣减的操作和b增加的操作,这两个操作就要就要是原子操作,要么都成功,要么都操作。如果不是原子操作,就会出现这样的问题,比如a扣款了,b却没有增加,所以必须两个操作是原子操作来避免出现问题。
如何实现原子操作
我要怎么实现原子操作呢,可以使用CAS来实现原子操作。
CAS的原理是什么
CAS就是比较和交换,利用了现代处理器都支持CAS的指令。在操作前先取出原值,然后进行操作,然后在更新修改后的新值的时候,用原值和内存中的原值进行比较,只有比较相同的的时候,才会做修改操作,把新值替换原值。而当比较不一致的时候,就不做修改,然后再取出新的原值,重新计算,然后再次判断,重复这个操作。
从图中也可以看出,先取出旧值,然后计算到新值,用旧值和内存中的变量比较,相等则更新,不想等则在循环这个过程。
CAS的问题
CAS也会出现一些问题,一起来看下
ABA问题
什么是ABA问题?ABA问题怎么解决?
如果内存中的旧值是A,在更新的时候检查的值还是A,这个时候能说明其他线程没有改变过这个值吗?
但是不一定的,可能某个线程给她改变成了B,然后又改成了A,这个时候其实是改动过的,但是CAS操作就会误认为他没有改变过,但实际上是已经改变了,这个问题就叫做ABA问题。
为了解决这个问题,就产生了一个版本号的概念,我有一个版本号来标识我修改了几次,即时在发生ABA这种操作,但是版本号是会随着变化的,这时候我在判断值是或否相等时,还会加上版本号是否相等,这就可以解决ABA问题。
开销问题
什么是开销问题?
因为CAS在计算值是否相等的过程中,使用的自旋,当判断的值不想等,会一直循环做这个操作,直到成功,如果CAS一直失败的话,会对CPU带来很大的开销。
只能保证一个共享变量的原子操作?
当我们对一个共享的变量做操作的试试,我可通过CAS的方式保证是原子操作,,但是对多个共享变量操作是,循环的CAS就不能保证是原子操作了,因为每个CAS只是一个变量,操作多个变量就是多个操作,就无法保证操作的原子性了,这时候就需要使用锁来保障原子性。