ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

聊聊CAS - 面试官最喜欢问的并发编程专题

2020-03-11 18:04:37  阅读:252  来源: 互联网

标签:var5 面试官 var1 var2 CAS 内存 聊聊 操作


什么是CAS

学习Java并发编程,CAS(Compare And Set)机制都是一个不得不掌握的知识点。除了通过synchronized进行并发控制外,还可以通过CAS的方式控制,大家熟悉的ReentrantLock内部实现大量采用CAS进行控制。

CAS即Compare and Swap,即比较并交换。

CAS有三个操作数:内存值V、预期值A、要修改的值B,当且仅当预期值A和内存值V相同时,才将内存值修改为B,否则什么都不做。最后返回现在的V值。

CAS在任何一种情况下,都会返回V的真实值。(这个变量称为compare-and-set,无论操作是否成功都会返回。)CAS的意思是:“我认为V的值应该是A,如果是,那么将其赋值为B,若不是,则不修改,并告诉我应该为多少”。CAS是一项乐观技术,它抱着成功的希望进行更新,并且如果另一个线程在上次检查后更新了该变量,它能够发现错误。

 

聊聊CAS - 面试官最喜欢问的并发编程专题

 

 

CAS是由CPU指令来保证的,大多数的处理器都支持都实现了CAS指令。

 

CAS的优点

保证原子性的方式只有加锁,无论是内置锁(synchronized),还是显示锁(ReentrantLock),加锁意味着线程阻塞,如果竞争激烈,很可能导致频繁的线程上下文切换,从而大大降低了性能。

CAS机制是一种乐观锁,可以避免这些问题,使得执行效率很大的提高。

 

CAS典型应用场景

1、乐观锁思想

CAS解决并发的思路可以在很多场景中借鉴,在数据库使用中,可以采用这种方式来避免加锁操作,比如大家学习Hibernate时候的乐观锁。

2、Java Concurren

Java Concurrent包下大量使用CAS实现并发控制,比如Atomic*,ReentrantLock等。

比如AtomicInteger中,就使用CAS。

Java无法直接访问底层操作系统,而是通过本地(native)方法来访问。JVM开了一个后门,JDK中有一个类Unsafe,它提供了硬件级别的原子操作。

例如AtomicInteger的getAndSet方法:

public final int getAndSet(int newValue) {
     return unsafe.getAndSetInt(this, valueOffset, newValue);
 }

unsafe类的getAndSetInt

public final int getAndSetInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);//根据地址和偏移量获取数值
} while(!this.compareAndSwapInt(var1, var2, var5, var4));//重复尝试CAS操作
return var5;
}

通过调用unsafe的getlntVolatile(var1,var2),这是个native方法,其实就是获取var1中,var2偏移量处的值。var1就是Atomiclnteger对象本身,var2就是我们前面提到的偏移地址,这样我们就从内存里获取到现在偏移地址处的值了。

再通过compareAndSwapInt操作输入原值var5和目标值var4,如果操作成功返回,操作失败重新读取内存数据再次进行compareAndSwapInt直到成功。

 

CAS的缺点

CAS虽然很高效的解决原子操作,但是CAS仍然存在三大问题。ABA问题,循环时间长开销大和只能保证一个共享变量的原子操作。

1)ABA问题

CAS操作需要检查当前内存的变量值是否和刚刚读取的值相同,假设一个变量是A,变成了B,之后又变成了A,所以在进行CAS操作的时候检查到它的值没有发生变化。ABA的解决方案就是加上版本号1A->2B->3A,类似这种。java先行者们也给我们提供了AtomicStampedReference来解决ABA的问题,其中的预期标志也类似于版本号的功能。

2)循环时间长开销大

多线程竞争激烈的情况下进行CAS操作,会导致某些线程长时间空循环,也就是说它什么都没做,只是不停地在浪费处理器的处理时间而已。

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

一个共享变量的操作可以用CAS保证其原子性,多个共享变量的操作,循环CAS是无法保证其原子性的。有个取巧的办法,java先行者设计的AtomicReference类,我们可以通过将多个变量放到一个对象里面,然后由AtomicReference进行原子性地更新。

 

欢迎大家讨论并发的相关问题,也可以加我的头条号: IT技术研习社 。

 

标签:var5,面试官,var1,var2,CAS,内存,聊聊,操作
来源: https://www.cnblogs.com/junyang/p/12464007.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有