Java并发笔记 (9)---- AQS示例


队列同步器 AbstractQueuedSynchronizer(以下简称 A.Q.S),是用来构建锁或者其他同步组
件的基础框架。

同步器是实现锁(也可以是任意同步组件)的关键

  • 锁是面向使用者的,它定义了使用者与锁交互的接口
  • 同步器面向的是锁的实现者,它简化了锁的实现方式

队列同步器的接口与示例

同步器的设计是基于模板方法模式的

重写同步器指定的方法时,需要使用同步器提供的如下3个方法来访问或修改同步状态:

  1. getState():获取当前同步状态。
  2. setState(int newState):设置当前同步状态。
  3. compareAndSetState(int expect,int update):使用CAS设置当前状态(原子操作)。

同步器可重写的方法:

// 尝试获取同步状态,当前状态符合预期,进行CAS设置同步状态
protected boolean tryAcquire(int arg);

// 独占式释放同步状态,同步队列中的线程将有机会获取同步状态
protected boolean tryRelease(int arg);

// 共享式获取同步状态,>=0,表示获取成功,反之,失败
protected int tryAcquireShared(int arg);

// 共享式释放同步状态
protected boolean tryReleaseShared(int arg);

// 表示当前线程是否持有同步状态
protected boolean isHeldExclusively() ;

实现自定义同步组件时,将会调用同步器提供的模板方法:

// 独占式获取同步状态
public final void acquire(int arg);
    
//该方法响应中断
public final void acquireInterruptibly(int arg);

//在上面的基础上加了超时限制
public final boolean tryAcquireNanos(int arg, long nanosTimeout)
            throws InterruptedException;

// 共享式的获取同步状态
public final void acquireShared(int arg);
public final void acquireSharedInterruptibly(int arg);
public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout)
            throws InterruptedException;

// 独占式释放同步状态
public final boolean release(int arg);

// 共享式释放同步状态
public final boolean releaseShared(int arg);

// 获取同步队列中的线程
public final Collection<Thread> getQueuedThreads()

同步器提供的模板方法基本上分为3类:独占式获取释放同步状态共享式获取释放同步状态查询同步队列中的等待线程情况。

public class Mutex implements Lock {
    // 静态内部类,自定义同步器
    private static class Sync extends AbstractQueuedSynchronizer {
        // 是否处于占用状态
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }
        // 当状态为0的时候获取锁
        public boolean tryAcquire(int acquires) {
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }
        // 释放锁,将状态设置为0
        protected boolean tryRelease(int releases) {
            if (getState() == 0) throw new
                    IllegalMonitorStateException();
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }
        // 返回一个Condition,每个condition都包含了一个condition队列
        Condition newCondition() { return new ConditionObject(); }
    }
    // 仅需要将操作代理到Sync上即可
    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));
    }
}

上述示例中,独占锁Mutex是一个自定义同步组件,它在同一时刻只允许一个线程占有锁。Mutex中定义了一个静态内部类,该内部类继承了同步器并实现了独占式获取和释放同步状态。在tryAcquire(int acquires)方法中,如果经过CAS设置成功(同步状态设置为1),则代表获取了同步状态,而在tryRelease(int releases)方法中只是将同步状态重置为0。用户使用Mutex时并不会直接和内部同步器的实现打交道,而是调用Mutex提供的方法,在Mutex的实现中,以获取锁的lock()方法为例,只需要在方法实现中调用同步器的模板方法acquire(int args)即可,当前线程调用该方法获取同步状态失败后会被加入到同步队列中等待,这样就大大降低了实现一个可靠自定义同步组件的门槛。

next: AQS 源码之同步队列+独占式同步状态

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值