了解java软件开发行业的朋友们,你是否也了解并使用过cas算法,知道cas有啥优缺点吗?如何使用呢?有兴趣的朋友可以跟小编一起看看。
CAS是英文单词CompareAndSwap的缩写,中文意思其实是:比较并替换。CAS需要有3个操作数:内存地址V,旧的预期值A,即将要更新的目标值B。
所以CAS指令执行时,当且仅当内存地址V的值与预期值A相等的时候,将内存地址V的值修改成为了B,否则就什么都不做。整个比较并替换的操作是一个原子操作。
CAS是种乐观锁技术,就是当多个线程尝试使用CAS同时去更新同一个变量的时候,只有其中一个线程可以更新变量的值,那么其它线程都失败了,失败的线程并不会被挂起的,而是被告知在这次竞争中失败,并可以再次尝试。
概述如下:CAS(Compare-and-Swap),即为比较并替换,是一种实现并发算法时常用到的技术,Java并发包中的很多类都使用了CAS技术呢。
类似于 CAS 的指令允许算法执行读-修改-写操作,而不用害怕其他线程同时修改变量,因为如果其他线程也修改变量的话,那么CAS会检测它(并失败),算法可以对该操作重新计算。
CAS无锁算法的C实现如下示例:
int compare_and_swap(int * reg, int oldval, int newval) { ATOMIC(); int old_reg_val = * reg; if (old_reg_val == oldval) * reg = newval; END_ATOMIC(); return old_reg_val; }
CAS的缺点,CAS虽然很高效的解决了原子操作问题,但是CAS仍然存在三大问题。
循环时间长开销很大。
只能保证一个共享变量的原子操作。
ABA问题。
循环时间长开销很大:
我们可以看到getAndAddInt方法执行时,如果CAS失败,会一直进行尝试。如果CAS长时间一直不成功,可能会给CPU带来很大的开销。
只能保证一个共享变量的原子操作:
当对一个共享变量执行操作时,我们可以使用循环CAS的方式来保证原子操作,但是对多个共享变量操作时,循环CAS就无法保证操作的原子性,这个时候就可以用锁来保证原子性。
如果在这段期间它的值曾经被改成了B,后来又被改回为A,那CAS操作就会误认为它从来没有被改变过。这个漏洞称为CAS操作的“ABA”问题。Java并发包为了解决这个问题,提供了一个带有标记的原子引用类“AtomicStampedReference”,它可以通过控制变量值的版本来保证CAS的正确性。因此,在使用CAS前要考虑清楚“ABA”问题是否会影响程序并发的正确性,如果需要解决ABA问题,改用传统的互斥同步可能会比原子类更高效。
优点是可以避免优先级倒置和死锁等危险,竞争比较便宜,协调发生在更细的粒度级别,允许更高程度的并行机制等等。JAVA对CAS的支持,在JDK1.5 中新增 java.util.concurrent (J.U.C)就是建立在CAS之上的。相对于 synchronized 这种阻塞算法,CAS是非阻塞算法的一种常见实现。所以J.U.C在性能上有了很大的提升。
那么以上就是本篇文章的所有内容了,还想了解更多java架构师的相关信息,记得来关注本站消息哦。