栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

Java并发—利用AQS实现自定义锁

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java并发—利用AQS实现自定义锁

目录

什么是AQS

AQS原理

利用AQS实现自定义锁


什么是AQS

AQS(AbstractQueuedSynchronizer),中文名抽象队列同步器

AQS定义了一套多线程访问共享资源的同步器框架,主要用来自定义锁和同步器

AQS原理

AQS 核心思想:

  • 如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。
  • 如果被请求的共享资源被占用,将暂时获取不到锁的线程加入到阻塞队列中,等待被唤醒和锁的分配

实现核心思想的的队列:CLH队列

CLH队列是一个虚拟的双向队列,AQS 是将每条请求共享资源的线程封装成一个 CLH 锁队列的一个结点(Node)来实现锁的分配。

共享资源用 volatile 关键词修饰,保证线程间的可见性

   
    private volatile int state;

0状态表示空闲,1状态或以上表示不空闲

共享资源(state)的访问方式有三种:  

  1. getState()   获得共享资源状态
  2. setState()   设置共享资源状态
  3. compareAndSetState() 更改共享资源状态(底层unsafe类)

 源代码如下

    
    protected final int getState() {
        return state;
    }

    
    protected final void setState(int newState) {
        state = newState;
    }
    
    protected final boolean compareAndSetState(int expect, int update) {
        // See below for intrinsics setup to support this
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }

利用AQS实现自定义锁

一:首先创建一个类实现Lock接口,它有6个方法需要实现

  1. lock():加锁(不成功进入阻塞队列等待)
  2. lockInterruptibly():是否加锁可打断
  3. tryLock()://加锁(不成功不会进入阻塞队列等待,可以去做其他事情)
  4. tryLock(long time,TimeUnit unit):加锁(规定时间内未获得则放弃加锁)
  5. unlock():释放锁
  6. newCondition():创建条件变量

二:创建一个内部类,继承AbstractQueuedSynchronizer

可以根据需求重写具体方法,总共有5种方法

  1. isHeldExclusively():该线程是否正在独占资源。只有用到condition才需要去实现它。
  2. tryAcquire(int):独占方式。尝试获取资源,成功则返回true,失败则返回false。
  3. tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false。
  4. tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。
  5. tryReleaseShared(int):共享方式。尝试释放资源,如果释放后允许唤醒后续等待结点返回true,否则返回false。

三:我需要自定义一个独占锁,不可重入,具有变量条件的锁

分析

  • 独占锁:AQS同步器中需要重写独占方式的获取资源tryAcquire(int)和释放资源tryRelease(int)方法
  • 不可重入:AQS同步器需要实现isHeldExclusively():
  • 具有条件变量:AQS同步器中 return new ConditionObject();

具体代码如下

//自定义锁(不可重入)(独占锁)(条件变量)
class MyLock implements Lock{
    //内部类,AQS同步器类
    class MySync extends AbstractQueuedSynchronizer{
        @Override
        protected boolean tryAcquire(int arg) {
            if (compareAndSetState(0,1)){
                System.out.println("获得锁成功");
                //加上了锁,并设置owner为当前线程
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            System.out.println("获得锁失败");
            return false;
        }

        @Override
        protected boolean tryRelease(int arg) {
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        @Override
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }

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

    private MySync mySync = new MySync();

    @Override //加锁(不成功进入阻塞队列等待)
    public void lock() {
        mySync.acquire(1);
    }

    @Override //加锁可打断
    public void lockInterruptibly() throws InterruptedException {
        mySync.acquireInterruptibly(1);
    }

    @Override //加锁(不成功不会进入阻塞队列等待,可以去做其他事情)
    public boolean tryLock() {
        return mySync.tryAcquire(1);
    }

    @Override //尝试加锁 带时间
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return mySync.tryAcquireNanos(1,unit.toNanos(time));
    }

    @Override //释放锁
    public void unlock() {
        mySync.release(1);
    }

    @Override //创建条件变量
    public Condition newCondition() {
        return mySync.newCondition();
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1018465.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号