zoukankan      html  css  js  c++  java
  • AQS原理

    AQS原理

    AQS是一个用来创建锁和同步器的框架,使用AQS能简单且高效的构造出应用广泛的大量的同步器;比如我们提到的RenentranLock,Semphore。,其他的诸如ReentrantReadWriteLock,synchronousQueue,FutureTask等等皆是基于AQS的,当然,我们自己也能利用AQS非常轻松容易地构造出符合自己同步需要需求的同步器;

     

    AQS原理概览;

    AQS核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的共享线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是CLH队列锁实现的;即将暂时获取不到的锁加入到队列中;

    CLH队列是一个虚拟的双向队列(虚拟的双向队列即不存在队列实例,仅存在结点之间的联系)。AQS是将每条请求共享资源的线程封装成一个CLH锁队列的一个结点来实现锁的分配;

    AQS对资源的共享方式

    AQS定义两种资源共享方式

    EXclusive:(独占)只有一个线程能执行;如reentrantlock。可分为公平锁和非公平锁;

    公平锁:按照线程在队列中的排队顺序;先到者拿到锁;

    非公平锁:当线程要获取锁,无视队列顺序直接去拿锁;谁抢到就是谁的;

    Share:(共享)多个线程可同时执行,如Semaphone/CountdownLatch。

    AQS底层使用了模板方法模式;

    同步器的设计方法是基于模板方法模式,如果需要自定义同步器一般的方式是这样,

    1. 使用者继承AbastractSynchronzier并重写制定的方法;

    2. 将AQS组合在自定义同步组件的实现中,并调用其模板方法,而这些模板方法会调用使用者重写的方法;

    需要重写的方法:

    isHeldExclusively()://该线程是否正在独占资源;只有用到condition才需要去实现它;

    tryAcquire()://独占方式,尝试获取资源,成功则返回true,失败则返回false;

    tryReLease()://独占方式,尝试释放资源,成功则返回true,失败则返回false;

    tryAcquireShared(int)://共享方式,尝试获取资源,负数表示失败,0表示成功,但没有剩余可用资源,整数表示成功,且有剩余资源;

    tryReleaseShared(int):////共享方式,尝试释放资源,负数表示失败,0表示成功,但没有剩余可用资源,整数表示成功,且有剩余资源;

    默认情况下,每个方法都抛出UnSupportedOperationException,这些方法的实现必须是内部线程安全的,并且通常简短而不是应该阻塞,AQS类中的其他方法都final;所以无法被其他类使用,只有这几个方法可以被其他类使用;

    以Renentrantlock为例,state初始化为0;表示未锁定状态,A线程lock()时,会调用tryAcquire()独占该锁并将state+1;此后,其他线程tryAcquire()时就会失败,直到A线程unlock到state=0(即释放锁位)为止,其他线程才有机会获取该锁,当然,释放锁之前,A线程是可以重复获取此锁的(state会累加),这就是可重入的概念,但要注意,获取多少次就要释放多少次,这样才能保证state是能回到零态的;

    再以countdownLatch为例,任务分为N个子线程去执行,state也初始化为N(注意N要与线程个数一致)。这N个子线程是并行执行的,每个子线程执行后cutdown()一次,state会CAS减1,等到所有子线程都执行完后(即state=0),会unpark()主调用线程,然后主调用线程就会从await()函数返回,继续后动作;

    一般自定义同步器要么是独占方法,要么是共享方式,他们只需实现try-acquire-tryrealse、tryAcquireShared-tryRelaseShared的一种即可;但AQS也支持自定义同步器同时实现独占和共享两种方式:如reentrantwriteLock。

    文章参考自:https://github.com/Snailclimb

  • 相关阅读:
    Eclipse 快捷键大全
    js字符串变量赋值的时候,一行写不下,想在下一行继续写
    java.lang.ClassNotFoundException: com.opensymphony.xwork2.util.TextUtils
    JS调用iframe父窗口元素和子窗口元素的方法
    no JMagick in java.library.path
    数据库建立索引的原则
    Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
    软件项目管理心得
    Errors running builder JavaScript Validator的问题
    21. Session Management
  • 原文地址:https://www.cnblogs.com/yjxs/p/9917361.html
Copyright © 2011-2022 走看看