CAS和AQS一文搞懂

Posted JF Coder

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CAS和AQS一文搞懂相关的知识,希望对你有一定的参考价值。

JAVA多线程,面试官喜欢问的东西

一些概念的东西

原子性就是指该操作是不可再分的。不论是多核还是单核,具有原子性的量,同一时刻只能有一个线程来对它进行操作。简而言之,在整个操作过程中不会被线程调度器中断的操作,都可认为是原子性。比如 a = 1;

非原子性:也就是整个过程中会出现线程调度器中断操作的现象
类似"a ++"这样的操作不具有原子性,因为它可能要经过以下两个步骤:

(1)取出 a 的值

(2)计算 a+1

如果有两个线程t1,t2在进行这样的操作。t1在第一步做完之后还没来得及加1操作就被线程调度器中断了,于是t2开始执行,t2执行完毕后t1开始执行第二步(此时t1中a的值可能还是旧值,不是一定的,只有线程t2中a的值没有及时更新到t1中才会出现)。这个时候就出现了错误,t2的操作相当于被忽略了

JAVA的线程调度—抢占式调度(优先级)


CAS—(Compare And Swap)比较并交换

采用乐观锁思想—总是认为自己可以完成操作

在多个线程操作一个变量时,只有一个线程会成功更新,其他失败,失败线程允许重试

CAS自旋等待

用锁或 synchronized 关键字可以实现原子操作,那么为什么还要用 CAS 呢,因为加锁或使用 synchronized 关键字带来的性能损耗较大,而用 CAS 可以实现乐观锁,它实际上是直接利用了 CPU 层面的指令,所以性能很高。

那么CAS 是怎么样实现自旋锁,CAS 利用 CPU 指令保证了操作的原子性,以达到锁的效果,至于自旋,一般是用一个无限循环实现。这样一来,一个无限循环中,执行一个 CAS 操作,当操作成功,返回 true 时,循环结束;当返回 false 时,接着执行循环,继续尝试 CAS 操作,直到返回 true。

进入CAS源码看
import java.util.concurrent.atomic.AtomicInteger;

以原子方式将值设置为给定的更新值(update),如果当前值等于期望值(expect)。 返回ture,更新变量的值,实际值不等于期望值返回false,线程什么都不做,CAS返回当前变量值;

public final boolean compareAndSet(int expect, int update) 
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    

进去unsafe.compareAndSwapInt(this, valueOffset, expect, update);它是个 native方法,用 c++ 实现,有兴趣的可以去看看JDK源代码中safe.cpp文件,所以CAS直接跟操作系统进行操作的;

public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);

public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);
CAS产生的ABA问题

什么是ABA?

上面我可以知道,CAS算法实现有一个重要的前提:需要取出内存中某一时刻的数据,然后在下一时刻进行比较,替换,在这个时间差,数据可能已经发生变化,这就导致了ABA问题;

解决方法:部分是通过加版本号(version)来解决,

AQS是一个抽象的队列同步器

AQS维护了一个volatile语义(支持多线程下的可见性)的共享资源变量state和一个FIFO线程等待队列(多线程竞争state被阻塞时会进入此队列)。java.util.concurrent.locks.AbstractQueuedSynchronizer 抽象类,简称 AQS

AQS共享资源的方式:独占式和共享式

AQS默认提供了独占式和共享式两种模式,JDK对应的实现有ReentrantLockReentrantReadWriteLock

独占式:只有一个线程能执行,具体的JAVA实现有ReentrantLock

共享式:多个线程同时执行

AQS 是基于 volitale 和 CAS 实现的,其中 AQS 中维护一个 valitale 类型的变量 state
来做一个可重入锁的重入次数,加锁和释放锁也是围绕这个变量来进行的。

推荐AQS解析


以上是关于CAS和AQS一文搞懂的主要内容,如果未能解决你的问题,请参考以下文章

面试官最喜欢问的CAS还不会?怎么和他吹牛?!一文带你搞懂CAS

一文彻底搞懂ReentrantLock原理基于AQS的公平锁+非公平锁

一文彻底搞懂ReentrantLock原理基于AQS的公平锁+非公平锁

图解源码之java锁的获取和释放(AQS)篇

一文带你精通CAS,由浅入深,直击灵魂

一文搞懂PyTorch与CUDA那些事