• 并发编程五 抽象队列同步器AQS应用Lock详解


    AQS应用之Lock

    1.1 并发之父

    Doug Lea(小名:李二狗)
    在这里插入图片描述
    生平不识Doug Lea,学懂并发也枉然;

    Java并发编程核心在于java.util.concurrent包,而juc当中的大多数同步器实现都是围绕着共同的基础行为,比如等待队列、条件队列、独占获取、共享获取等,而这个行为的抽象就是基于AbstractQueuedSynchronizer简称AQS,AQS定义了一套多线程访问共享资源的同步器框架,是一个依赖状态(state)的同步器。

    1.2 ReentrantLock

    ReentrantLock是一种基于AQS框架的应用实现,是JDK中的一种线程并发访问的同步手段,它的功能类似于synchronized是一种互斥锁,可以保证线程安全。而且它具有比synchronized更多的特性,比如它支持手动加锁与解锁,支持加锁的公平性。

    使用ReentrantLock进行同步
    ReentrantLock lock = new ReentrantLock(false);//false为非公平锁,true为公平锁
    lock.lock() //加锁
    //业务逻辑
    //.......
    lock.unlock() //解锁
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    ReentrantLock如何实现synchronized不具备的公平与非公平性呢?
    在ReentrantLock内部定义了一个Sync的内部类,该类继承AbstractQueuedSynchronized,对该抽象类的部分方法做了实现;并且还定义了两个子类:
    1、FairSync 公平锁的实现
    2、NonfairSync 非公平锁的实现
    这两个类都继承自Sync,也就是间接继承了AbstractQueuedSynchronized,所以这一个ReentrantLock同时具备公平与非公平特性。
    上面主要涉及的设计模式:模板模式-子类根据需要做具体业务实现

    1.3 AQS具备特性

    • 阻塞等待队列
    • 共享/独占
    • 公平/非公平
    • 可重入
    • 允许中断

    除了Lock外,Java.util.concurrent当中同步器的实现如Latch,Barrier,BlockingQueue等,都是基于AQS框架实现

    • 一般通过定义内部类Sync继承AQS
    • 将同步器所有调用都映射到Sync对应的方法

    AQS内部维护属性volatile int state (32位)

    • state表示资源的可用状态

    State三种访问方式

    • getState()、setState()、compareAndSetState()

    AQS定义两种资源共享方式

    • Exclusive-独占,只有一个线程能执行,如ReentrantLock
    • Share-共享,多个线程可以同时执行,如Semaphore/CountDownLatch

    AQS定义两种队列

    • 同步等待队列
    • 条件等待队列

    不同的自定义同步器争用共享资源的方式也不同。自定义同步器在实现时只需要实现共享资源state的获取与释放方式即可,至于具体线程等待队列的维护(如获取资源失败入队/唤醒出队等),AQS已经在顶层实现好了。自定义同步器实现时主要实现以下几种方法:

    • isHeldExclusively():该线程是否正在独占资源。只有用到condition才需要去实现它。
    • tryAcquire(int):独占方式。尝试获取资源,成功则返回true,失败则返回false。
    • tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false。
    • tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。
    • tryReleaseShared(int):共享方式。尝试释放资源,如果释放后允许唤醒后续等待结点返回true,否则返回false。

    1.4 同步等待队列

    AQS当中的同步等待队列也称CLH队列,CLH队列是Craig、Landin、Hagersten三人发明的一种基于双向链表数据结构的队列,是FIFO先入先出线程等待队列,Java中的CLH队列是原CLH队列的一个变种,线程由原自旋机制改为阻塞机制。
    在这里插入图片描述

    1.5 条件等待队列

    Condition是一个多线程间协调通信的工具类,使得某个,或者某些线程一起等待某个条件(Condition),只有当该条件具备时,这些等待线程才会被唤醒,从而重新争夺锁

    在这里插入图片描述

    锁三大核心原理AQS:

    1. 循环(自旋)
    2. LockSupport
    3. CAS: 比较与交换,compare and swap, 不管并发多高,都能保证原子性(加锁)
    4. queu队列

    公平锁:
    假如T0,T1, T2, T3这四个线程抢锁,T1抢上了,则T1、T2、T3进行排队,当T1执行完自己的业务后释放锁,释放锁后新线程T4线程也来抢锁,此时T4没有直接去抢,而是去排队;

    非公平锁

  • 相关阅读:
    【算法合集】学习算法第三天(二叉树遍历篇)
    百度超级链XuperChain使用JavaSDK接入
    基于energy score的out-of-distribution数据检测,LeCun都说好 | NerulPS 2020
    QML布局管理之Layouts
    VirtualBox虚拟机安装Win10企业版
    C++ Reference: Standard C++ Library reference: C Library: ctime: difftime
    休息时间c++
    noip模拟赛多校第八场 T3 遥控机器人 (最短路 + 技巧拆点)
    内容安全(IPS入侵检测)
    2009-2018年各省涉农贷款数据(wind)
  • 原文地址:https://blog.csdn.net/qq_33417321/article/details/120815932