0
点赞
收藏
分享

微信扫一扫

AQS基础入门

janedaring 2021-09-28 阅读 152

AQS是JDK并发包下的一个基础类,或者模板类,JUC下的很多工具类都是基于它实现的。其内部:

  • 依靠内部维护一个FIFO的等待队列
  • 对于只依赖一个原子值来表示状态的同步机制来说很有用
  • 子类继承AQS来修改原子状态,从而实现相关同步操作。
    • getState()
    • setState()
    • compareAndSetState()

AQS支持排它模式和共享模式,等待在不同线程的共享同一个FIFO队列,目前大部分都会只实现一种机制,排它或者共享,JDK中有一个类同时实现了两种机制:ReadWriteLock

想要使用当前的类,重定义其几个方法:

  • tryAcquire 尝试获取独占锁,
  • tryRelease 尝试释放排它锁
  • tryAcquireShared 尝试获取共享锁,返回负数代表失败,返回0代表当前的锁获取成功,但是后续无法获取,返回正数,代表后续的节点仍然可以继续获取
  • tryReleaseShared 尝试释放共享锁
  • isHeldExclusively 是否排它状态

获取和释放操作本质即变更state。

再真正调用的时候则使用,AQS内部的方法,其会调用我们定义的几个方法,使用时:

  • acquire\acquireInterruptibly\tryAcquireNanos 获取排它锁
  • acquireShared\acquireSharedInterruptibly\tryAcquireSharedNanos 获取共享锁
  • release\releaseShared 释放锁

例如排它锁的实现形式:

Acquire:
     while (!tryAcquire(arg)) {
        // enqueue thread if it is not already queued;
        如果还没有加入队列,那么将当前线程加入队列       
        // possibly block current thread;
        可能block当前的线程
     }

 Release:
     if (tryRelease(arg))
        unblock the first queued thread;
        // 解锁第一个入队列的线程

JUC的CountdownLatch和ReentrantLock给了我们一个很经典的实现方式,后面我们再分析其具体实现。当前看下CountdownLatch代码:

public class CountDownLatch {
      
      // 实现同步机制
    private static final class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 4982264981922014374L;

        Sync(int count) {
            setState(count);
        }

        int getCount() {
            return getState();
        }

        protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }

        protected boolean tryReleaseShared(int releases) {
            // Decrement count; signal when transition to zero
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;
                int nextc = c-1;
                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            }
        }
    }

    private final Sync sync;

    public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

    public boolean await(long timeout, TimeUnit unit)
        throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

   
    public void countDown() {
        sync.releaseShared(1);
    }

    public long getCount() {
        return sync.getCount();
    }

}

下次再分析下AQS的具体方法含义。

举报

相关推荐

0 条评论