[java并发设计]cas的原理

1.什么是cas?

cas 英文全称是Compare and Swap,翻译过来就是比较交换.

CAS操作包含三个操作数——需要读写的内存值(V)、预期原值[进行比较的值](A)和新值(B)。如果V的值与A值匹配时,那么就将该内存位置的值更新为新值(B),否则不做任何操作。\color{red}{这一块需要了解主内存(V是主内存的地址,该地址会被多个线程操作)和本地(本地内存存储这A值)的区别,这里的cas是以单个线程为主体,判断是否存在其他线程修改主内存的数据}

2.CAS原理

cas是通过处理器的CMPXCHG指令实现的。

image.png

CMPXCHG是汇编指令
作用:比较并交换操作数.
如:CMPXCHG r/m,r 将累加器AL/AX/EAX/RAX中的值与首操作数(目的操作数)比较,如果相等,第2操作数(源操作数)的值装载到首操作数,zf置1。如果不等, 首操作数的值装载到AL/AX/EAX/RAX并将zf清0
该指令只能用于486及其后继机型。第2操作数(源操作数)只能用8位、16位或32位寄存器。第1操作数(目地操作数)则可用寄存器或任一种存储器寻址方式。

2.CAS的缺点

CAS虽然可以很高效的解决原子操作问题,但它仍然存在三大问题。

(1).ABA问题

ABA问题产生的原因:CAS操作的时候需要检查值有没有发生变化,如果没有发生变化则进行更新,但如果一个值原来是A,接着变成B,后来又变成A,在CAS操作的时候会发现它的值没有发生变化,但实际上值发生了变化。因此这种操作是有问题的。

解决思路:使用版本号。在变量前面追加上版本号,每次变量更新的时候把版本号自增,那么A-B-A 就会变成1A-2B-3A。从Java1.5开始JDK的atomic包里提供了一个类AtomicStampedReference来解决ABA问题。这个类的compareAndSet方法作用是首先检查当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果全部相等,则以原子方式将该引用和该标志的值设置为给定的更新值。

(2).循环时间开销大

自旋CAS如果长时间不成功,会给CPU带来非常大的执行开销。

(3).只能保证一个共享变量的原子操作

因为Java中的CAS操作只是对CPU的cmpxchg指令的一层封装,它的功能就是一次只能原子的修改一个变量,可以加锁来解决这个问题。或者利用AtomicReference把多个变量放入一个对象中进行CAS操作。

你可能感兴趣的:([java并发设计]cas的原理)