AQS笔记二 ---- 使用AQS自定义锁

AQS笔记二 ---- 自定义锁

AQS(AbstractQueuedSynchronizer) 队列同步器, AQS定义了一套多线程访问共享资源的同步器框架.

AQS 内部依赖的同步队列(一个FIFO双向队列)来完成同步状态的管理, 当前线程获取同步状态失败时, 同步器会将当前线程以及等待状态等信息构成一个节点(Node) 并将其加入到同步队列, 同时阻塞当前线程, 当同步状态释放时, 会将首节点中的线程唤醒, 使其再次尝试获取同步状态.

同步器是实现锁(也可以是任意同步组件)的关键, 在锁的实现中聚合同步器, 利用同步器实现锁的语义, 可以理解二者之间的关系: 锁是面向使用者的, 它定义了使用者与锁交互的接口, 隐藏了实现细节; 同步器是锁的实现者, 它简化了锁的实现方式, 屏蔽了同步状态管理, 线程的排队,等待与唤醒等底层操作。锁和同步器很好地隔离了使用者和实现者所需关注的领域;

同步器的设计是基于模板方法模式, 使用者需要继承同步器并重写指定的方法, 随后将同步器组合在自定义同步组件的实现中, 并调用同步器提供的模板方法;

一、实现自定义同步组件依靠的几个方法

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

  • getState() 获取当前同步状态;
  • setSate(int newState) 设置当前同步状态
  • compareAndSetState(int expect, int update) 使用CAS设置当前状态, 该方法能保证状态设置的原子性;

1.1 同步器可重写的方法

1254098-20180726223327670-1190660885.png

1.2 同步器提供的模板方法

实现自定义同步组件时, 会遇到调用同步器提供的模板方法, 模板方法如下:
1254098-20180726223732299-214941530.png

二、 自定义锁

2.1 非重入排他锁

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class Metex implements Lock {

    private static class Sync extends AbstractQueuedSynchronizer{
        // 是否处于占用状态
        protected boolean isHeldExclusively(){
            return getState() == 1;
        }
        // 尝试获取同步状态
        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 IllegalArgumentException();
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }
        // 返回一个Condition, 每个condition都包含一个condition队列
        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.tryRelease(1);
    }

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

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

转载于:https://www.cnblogs.com/jxkun/p/9374876.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值