目录
CAS:全称是Compare And Swap,即比较并交换。
它会把内存中的某个值,和寄存器A中的值进行比较,如果两个值相同,那么就把寄存器B中的值和内存中的这个值进行交换。
进行CAS的主要目的是将寄存器B中的值放到内存中。
用一个伪代码来解释CAS:
CAS最强大的地方在于,以上的操作是通过一个CPU指令完成的,所以它不仅高效,而且还是线程安全的。
什么是原子类?
在多线程环境下进行count++操作时,这种操作是线程不安全的,要想保证线程安全就得加锁,但是加锁又会导致效率降低。
所以我们可以使用CAS操作来实现一个原子的++操作,从而既保证了线程安全,也保证了效率问题。
AtomicInteger类就是一个典型的原子类~
伪代码解释原子类:
自旋锁:当锁被一个线程持有时,其他线程不会挂机等待,而是会反复询问当前的锁是否被释放,如果锁被释放,那么就可以第一时间获取到这个锁。
自旋锁的实现方式和原子类比较相似~
伪代码解释自旋锁:
这种实现方式的自旋锁会消耗大量CPU资源,如果预期锁竞争不太激烈时,比较适用自旋锁~
因此自旋锁也是一个轻量级锁,也是一个乐观锁~
在CAS进行到比较操作的时候,如果发现寄存器A中的值和内存中值M相同,此时,我们无法确定M是否是始终没发生过变化的M,还是说M经过了一些计算之后又变回了原来的M。
举个栗子:
假设男生A和女生B是一对情侣,有一天,他们分手了,都变成单身的状态。但是男生A又和女生C处了一段时间对象后分手了,于是他又以单身的状态和女生B复合。
在A和B分手期间,女生B无法确定男生A是否找其他妹子处过对象,还是说男生A分手后一直是单身的状态。
虽然ABA问题发生的概率极低,但也是一个隐患问题,我们需要想办法解决它~
我们可以记录M的修改次数(版本号),或上次修改时间,两个值都是只增不减,以此来解决ABA问题~
那么在进行CAS比较的时候,我们不用比较M和A的值,而是比较M的版本号,或者M的上次修改时间:
(a) 如果当前版本号和读到的版本号相同,则修改数据,并把版本号+1;
(b) 如果当前版本号大于读到的版本号,则操作失败。