JAVA并发编程(9)-JAVA中的锁及实现方式(AQS)

Lock接口
锁是用来控制多个线程访问共享资源的。在java1.5之前主要依靠synchronized 关键字来实现锁的功能。1.5之后java并发包中引入了Lock接口来实现锁功能。
Lock接口常用方法:
void lock() 阻塞式获取锁 获取成功才能返回
void lockInterruptibly() 可中断获取锁 和lock 不同之处就是可以响应中断
boolean tryLock() 非阻塞式获取锁 立即返回 获取到返回 ture 否则返回 false
boolean tryLock(long,unit) 超时获取锁 三种返回情况 :超时时间内获取到锁,超时时间内被中断 ,超过超时时间
void unlock() 释放锁
Condition new Condition() 获取锁的ConditionObject对象

Lock和synchrinaized 对比
synchronized 使用简单,可以隐式的获取和释放锁,使用简单,功能固化,只能阻塞等待锁,而且是排他的。
Lock 实现程序同步比较灵活。比如 一个场景,要先获得锁A,然后再获取锁B,当锁B获得后,释放锁A同时获取锁C,当锁C获得后,再释放B同时获取锁D 。这种场景synchronized无法实现
Lock可以无阻塞的获取锁、超时阻塞获取锁 、可以实现共享锁。 这些 synchronized无法实现
Lock 能被中断的获取锁 ,获取到锁的线程能够响应中断,当获得锁的线程被中断时,抛出中断异常同时释放锁。

锁的实现–AQS介绍
并发包中锁都是基于队列同步器(AbstractQueuedSynchronizer 以下简称AQS)实现。AQS是并发包的作者(DougLea)提供的用来构建锁及其他同步组件的基础框架。它使用了一个int类型成员变量state表示同步状态。并内置了FIFO队列来实现线程的排队工作。开发者只需要在自己的同步组件中继承AQS这个类,并实现它的抽象方法,一些复杂的底层的操作作者都已经实现,在需要时调用即可。比如同步器提供了3个方法(getState()、setState(int newState)和compareAndSetState(int expect,int update))来进行同步状态的访问和更新。这个其实就是设计模式中的模板方法模式

AQS部分属性如下
在这里插入图片描述
对于需要重写和覆盖的方法 都直接抛出了异常,就是说这些方法必须重写才能被调用,比如 tryAcquire()如下:
在这里插入图片描述
AQS可重写得方法及作用总结如下:
在这里插入图片描述
AQS已经封装好的模板方法基本上分为三类独占式获取释放同步状态、共享式获取释放同步状态和查询同步队列中的线程情况,具体如下:

在这里插入图片描述

用AQS实现一个排它锁
这里我们通过AQS来实现一个排它锁,某一时刻只允许一个线程获得锁。额
实现方式:
1、实现 lock接口,接口中的方法用来对外提供api 用于获取和释放锁
2、 定义一个静态内部类,继承AbstractQueuedSynchronizer ,并且由于我们要实现的是排他锁,所以需要重写 tryAcquire tryRelease 方法
3、在lock 接口方法中,调用 AQS的方法来实现 加锁 解锁 等逻辑。

由实例可以看出 Lock 接口 是面向 编程人员的。编程人员调用 lock api 来实现加锁解锁等操作。而AQS是面向计算机的,AQS实现了很多的底层操作。而我们写的lock 实现类就是把AQS封装到了一个接口中。

class Mutex implements Lock {
    // 定义静态内部类,继承AQS  并实现  isHeldExclusively  tryAcquire  tryRelease
    private static class Sync extends AbstractQueuedSynchronizer {
        // 是否处于占用状态 
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }
        // 当状态为0的时候获取锁
        public boolean tryAcquire(int acquires) {
            if (compareAndSetState(0, 1)) {
                //获取锁成功 将AQS 的拥有者设置为当前线程
                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));
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

catch that elf

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值