前言
CAS机制听起来很高大上,其实就可以把他理解为与synchronized
并列的一种方式。我个人把他理解为是实现线程同步的另外一种方式(虽然本质上是异步访问,但是最终的结果与同步访问的结果是一样的)或者说,从微观上来看是异步的,但是从宏观上来看是同步的。就类似并发一样,微观上是每一时刻只执行一个进程,但是宏观上来看是多进程并发,一个道理。
1.为啥要用CAS机制?
在正式介绍CAS之前,不如聊聊它与synchronized
的区别,或者它的特点,为啥要用CAS机制?
那就不得不提到悲观锁和乐观锁的概念了。
所谓悲观锁,就类似于synchronized
这样的,多个线程访问被synchronized
修饰的代码块,谁抢到锁,谁就执行。所以synchronized
默认是高并发并且竞争很激烈,所以它很“悲观”。而乐观锁就恰恰相反,它认为程序的竞争不激烈,没有人会跟我竞争这个变量,所以它就很“乐观”。而CAS操作的锁就是乐观锁的典型例子。
悲观锁如synchronized
的效率其实是相对不高的,因为上下文切换需要耗费很多资源,而乐观锁的效率在大部分情况下还是很高的。我们看这张图
lock
就是说的synchronized
,AtomicInteger
就是乐观锁。可以看到当线程数目多于2时,CAS机制的性能一般来讲就优于synchronized
了。
2.CAS原理
CAS的全称是Compare And Swap
,就是比较 和 交换。这是CAS的核心。
CAS机制当中使用了3个基本操作数:内存地址(我们不用管),旧的预期值A,要修改的新值B。在正式修改变量之前,它要将预期值A于在相应内存地址的实际值进行比较,如果相等,则将新值B替换到内存地址的实际值,如果不相等,则将此时的实际值作为新的预期值,然后再循环。
什么意思,多说无益,我们举个实际点的例子吧。比如说有一个变量number
,初始值为0.然后有两个线程对其进行number++
操作。让我们来看一下此时CAS的工作原理
假如线程1 的操作流程是这样的
(这里在预期的操作那里搞错了,是得到新值1,预期的旧值为0)
那么线程2 的操作流程就是这样的