Java并发编程--AQS与自定义锁

什么是AQS

AQS(Abustact Queued Synchronizer 抽象队列化同步器)是用来为Java的并发同步组件提供统一的底层支持,例如 ReentrantLock, CountdowLatch 都是基于AQS实现的。AQS采用模板方法设计模式,我们可以通过简单的继承实现模板方法,来自定义我们自己的锁。

 

AQS的常用方法

AQS定义两种资源共享方式:Exclusive(独占,只有一个线程能执行,如ReentrantLock)和Share(共享,多个线程可同时执行,如Semaphore/CountDownLatch)。

独占式获取(独占锁)
accquire
acquireInterruptibly
tryAcquireNanos

共享式获取(共享锁)
acquireShared
acquireSharedInterruptibly
tryAcquireSharedNanos

独占式释放锁
release

共享式释放锁
releaseShared

需要子类覆盖的流程方法
独占式获取  tryAcquire
独占式释放  tryRelease
共享式获取 tryAcquireShared
共享式释放  tryReleaseShared
这个同步器是否处于独占模式  isHeldExclusively

同步状态state:
getState:获取当前的同步状态
setState:设置当前同步状态
compareAndSetState 使用CAS设置状态,保证状态设置的原子性

 

AQS中的数据结构

AQS有2个重要组成部分:

  • state 同步状态:int 类型
  • 一个同步队列:当一个线程尝试获取锁时,如果已经被占用,此线程就作为一个节点添加到队尾,对头是成功获取锁的节点,对头释放锁后,会唤醒后面的节点,并出队。

 

自定义锁

实现Lock接口,方法通过AQS实现;在内部定义一个AQS,复写模板方法。其中state = 1表示获取到了锁, state = 0 表示这个锁没有线程拿到,不可重入。如果要做成可重入的,只需每次拿锁 stats + 1, 释放 stats - 1即可。 
当前这个是独占锁,而共享锁的实现类似;只需初始化定义stats = n,然后每次拿到锁之后 stats - 1, 当stats < 0 后等待。

注意所有拿锁的stats操作必须遵循CAS操作,即满足原子性。

public class SelfLock implements Lock {

    // state = 1表示获取到了锁, state = 0 表示这个锁没有线程拿到,不可重入
    private static class Sync extends AbstractQueuedSynchronizer {

        // 判别当前锁是否占用
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }

        protected boolean tryAcquire(int arg) {
            if(compareAndSetState(0, 1)) {
                // 设置当前线程拿到锁
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        protected boolean tryRelease(int arg) {
            if(getState() == 0) {
                throw new UnsupportedOperationException();
            }
            // 由于只有一个线程能到持有锁,故这里不需要CAS操作
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        Condition newCondition() {
            return new ConditionObject();
        }
    }

    private  final Sync sync = new Sync();

    @Override
    public void lock() {
        sync.acquire(1);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    @Override
    public boolean tryLock() {
        return sync.tryAcquire(1);
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(time));
    }

    @Override
    public void unlock() {
        sync.release(1);
    }

    @Override
    public Condition newCondition() {
        return sync.newCondition();
    }
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值