CAS与AQS

CAS和AQS

什么是CAS

比较并交换——乐观锁机制——锁自旋

概念以及特性

概念

​ CAS比较并交换,

  • CAS算法的过程:包含三个参数CAS(V,E,N)
    • V表示要更新的变量(内存值),E表示预期值(旧的),N表示新值
  • 当且仅当V等于E时,才会将V的值设为N,如果V和E不同,表示已经有其他线程最了更新,则当前线程什么都不做,最后CAS返回当前V的真实值
特性
  • 抱着乐观的态度进行的(乐观锁),总是以为自己可以成功完成操作,当多个线程同时使用CAS操作一个变量时,只有一个会胜出,并成功更新,其余都会失败,失败的线程不会挂起,只是被告知失败,并且允许再次尝试,也允许失败的线程放弃操作。
  • 使得CAS操作即使没有锁,也可以发现其他线程对当前线程的干扰,并进行恰当的处理

原子包java.util.concurrent.atomic(锁自旋)

​ 此包里提供了一组原子类,其基本的特性即使在多线程环境下,当有多个线程同时执行这些类的实例包括的方法时,具有排他性,即当某个线程进入方法,执行其中的指令时,不会被其他线程打断,而别的线程就想自旋锁一样,会一直等待到改方法执行完毕,才由JVM从等待队列中选择另一个线程进入。

​ CAS是非阻塞算法的一种常见实现,由于一般CPU切换事件比CPU指令集操作更长,所有J.U.C在性能上有了很大的提高

ABA问题

​ CAS可能会导致ABA问题,CAS算法实现的一个重要前提需要取出内存中某时刻的数据,而在下时刻比较并替换,那么在这个时间差会导致数据的变化

​ 部分乐观锁的实现是通过版本号的方式来解决ABA问题,乐观锁每次在执行数据的修改操作时,都会带上一个版本号。

AQS

​ 抽象的对象式的同步器,AQS定义了一套多线程访问共享资源的同步器框架,许多同步类实现都依赖于它。

  • 内部实现的关键是:先见先出队列,state状态
  • 定义了内部类ConditionObject
  • 拥有两张线程模式
    • 独占模式:只有一个线程能执行(ReentrantLock)
    • 共享模式:多个线程可同时执行,如Semaphore/CountDownLatch
  • 一般叫AQS为同步器
  • 只是一个框架,具体资源的获取/释放方式由自定义同步器去实现。

同步状态

  • volatile修饰实现线程可见性
  • 修改state状态时使用CAS算法来实现

先见先出队列

  • 这个队列被称为CLH队列,是一个双向队列

主要方法

acquire方法
  • 获得独占锁的过程就是在acquire中定义的,该方法用来了模板设计模式,由子类实现
  • 过程
    • acquire(int)尝试获取资源,如果获取失败,将线程插入等待队列
    • 插入等待队列后,并没有放弃获取资源,而是根据前置节点状态判断是否应该继续获取资源
    • 如果前置节点是头节点,继续尝试获取资源,如果前置节点是SIGNAl状态就中断当前线程,否则继续尝试获取资源。直到当前的线程被park()获取到资源
    • 结束
release方法
  • 释放独占锁的过程就是在其中定义的
  • 过程
    • 首先调用子类的tryRealse()方法释放锁,然后唤醒后续节点
    • 在唤醒的过程中,需要判断后续节点是否满足情况
    • 如果后续节点不为空且不是作废状态,则唤醒这个后续节点
    • 否则从tail节点向前寻找合适的节点,如果找到,则唤醒

猜你喜欢

转载自blog.csdn.net/issunmingzhi/article/details/105600163