JAVA CAS
程序员文章站
2022-05-04 16:23:56
...
1.概念
CAS:Compare and Swap,即比较再交换。是通过原子指令来实现多线程的同步功能,将获取存储在内存地址的原值和指定的内存地址进行比较,只有当他们相等时,交换指定的预期值和内存中的值,这个操作是原子操作,若不相等,则重新获取存储在内存地址的原值。
jdk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronouse同步锁的一种乐观锁。JDK 5之前Java语言是靠synchronized关键字保证同步的,这是一种独占锁,也是是悲观锁。
CAS是一种无锁算法,有3个关键操作数,内存地址,旧的内存中预期值,要更新的新值,当内存值和旧的内存中预期值相等时,将内存中的值更新为新值。
CAS属于乐观锁,乐观锁就是每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。
synchronized是悲观锁,被一个线程拿到锁之后,其他线程必须等待该线程释放锁,性能较差。
2.代码
package com.njitt.util;
import java.util.concurrent.atomic.AtomicInteger;
public class CASDemo{
public static void main(String[] args){
AtomicInteger atomicInteger=new AtomicInteger(5);
/**第一次看主物理内存中的值是否为5,如是则替换为2019*/
/**第一次看主物理内存中的值是否为5,如是则替换为1024*/
System.out.println(atomicInteger.compareAndSet(5, 2019)+"\t current data:"+atomicInteger.get());
System.out.println(atomicInteger.compareAndSet(5, 1024)+"\t current data:"+atomicInteger.get());
}
}
3.图解
4.弊端
-
ABA问题
-
只能保证一个共享变量的原子操作
多个共享变量操作时,循环CAS就无法保证操作的原子性,这个时候就可以用锁。从java1.5开始,JDK提供了AtomicReference类来保证引用对象之间的原子性,就可以把多个变量放在一个对象里来进行CAS操作。
-
循环时间长CPU开销较大
在并发量比较高的情况下,如果许多线程反复尝试更新某一个变量,却又一直更新不成功,循环往复,会给CPU带来很大的压力。如下图所示,如果多个线程反复尝试更新某一个变量会导致while循环一直进行,从而导致开销较大。