AQS(AbstractQueuedSynchronizer)

AQS(锁的基类)

基础描述

AbstractQueuedSynchronizer(AQS)这个抽象类,是Java并发包 java.util.concurrent 的基础工具类,是实现 ReentrantLock、CountDownLatch、Semaphore、FutureTask 等类的基础。

AbstractQueuedSynchronizer从名字上就可看出本质是一个线程锁的等待队列(Queue),其内部维护着FIFO的双向队列,也就是CLH队列。

AbstractQueuedSynchronizer其实是锁的主体。Lock类会有一个AQS类型的属性来实现锁。

AQS实现锁:

1,Lock类会有一个AQS类型的属性sync,sync是AQS的子类,

重写了tryAcquire()函数获取锁和tryRelease()函数释放锁。

2,当前线程获取到锁标志:

AQS.state > 0 && AQS.exclusiveOwnerThread == 当前线程。

AQS原理:

AQS中维护着一个同步队列:

1,头结点head是一个哨兵节点或者是已经获取到锁的线程,只有第二个节点能够尝试获取锁。

2,第二个节点获取到锁之后变为头结点。

AQS获取锁:

1,通过acquire函数调用tryAcquire获取锁,如果tryAcquire获取到锁结束流程。

2,如果没有竞争到锁,当前线程会封装成Node节点插入等待队列尾部。

AQS释放锁:

通过release调用tryRelease释放锁,当前线程释放锁后通过unparkSuccessor唤醒下一个等待队列中的线程.

AQS实现DEMO

//JDK给出的一个实现AQS的Demo示例(独占锁)

class Mutex implements Lock, java.io.Serializable {

   private static class Sync extends AbstractQueuedSynchronizer {

       protected boolean isHeldExclusively() {

         return getState() == 1;

       }

       public boolean tryAcquire(int acquires) {

         assert acquires == 1;

         if (compareAndSetState(0, 1)) {

           setExclusiveOwnerThread(Thread.currentThread());

           return true;

         }

         return false;

       }

       protected boolean tryRelease(int releases) {

         assert releases == 1;

         if (getState() == 0)

           throw new IllegalMonitorStateException();

         setExclusiveOwnerThread(null);

         setState(0);

         return true;

       } 

       Condition newCondition() {

         return new ConditionObject();

       }   

       private void readObject(ObjectInputStream s)  throws IOException, ClassNotFoundException {

         s.defaultReadObject();

         setState(0);

       }

     }

     private final Sync sync = new Sync();

        public void lock() {

          sync.acquire(1);

        }

     public boolean tryLock() {

       return sync.tryAcquire(1);

     }

     public void unlock() {

       sync.release(1);

     }

     public Condition newCondition() {

       return sync.newCondition();

     }

     public boolean isLocked() {

       return sync.isHeldExclusively();

     }

     public boolean hasQueuedThreads() {

       return sync.hasQueuedThreads();

     }

     public void lockInterruptibly() throws InterruptedException {

       sync.acquireInterruptibly(1);

     }

     public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {

       return sync.tryAcquireNanos(1, unit.toNanos(timeout));

     }

}

1.AQS结构定义

//AQS结构定义

public abstract class AbstractQueuedSynchronizer ... {

  //AQS等待队列的节点数据结构

  static final class Node {

    static final Node SHARED = new Node(); //共享锁模式

    static final Node EXCLUSIVE = null; //独占锁模式

    线程状态,小于等于0表示是正常状态,大于0表示线程排队被取消.

    volatile int waitStatus; 

    volatile Node prev; /节点的前继节点,

    volatile Node next; //节点的后继节点

    volatile Thread thread; //节点对应的线程

    Node nextWaiter; //锁的模式(共享锁或独占锁)

  }

  

  private transient volatile Node head; //队列头部节点

  private transient volatile Node tail; //队列尾部节点

  private volatile int state; //存储锁的数量

  private transient Thread exclusiveOwnerThread; //当前持有锁的线程

}

  1. AQS.acquire函数

Lock.lock的入口:当前线程抢占锁资源,如果抢占成功函数返回true,否则不断尝试去抢占锁

//AQS(AbstractQueuedSynchronizer)抢占线程独占锁

public final void acquire(int arg) {

    //调用AQS的acquire函数,此函数会执行如下几个流程:

    //=>1,"tryAcquire"对当前线程进行加锁,如果加锁成功,直接结束流程,否则执行步骤2.

    //=>2,"addWaiter"线程加锁失败,把线程添加到等待队列中(队列尾部),并执行步骤3.

    //=>3,"acquireQueued"线程不断尝试抢占锁资源,如果抢占锁成功结束流程,否则执行步骤4.

    //=>4,"selfInterrupt"表示线程处于BLOCKED状态,同时线程是标记为中断的线程

//===>1,同时被标记中断(读取中断标记后标记位会被清理),重新把线程标记为中断状态.

//===>2,在重新调用selfInterrupt会抛出”InterruptedException”异常(因为线程是BLOCKED状态),

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值