zoukankan      html  css  js  c++  java
  • AQS笔记二 ---- 使用AQS自定义锁

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

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

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

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

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

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

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

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

    1.1 同步器可重写的方法

    1.2 同步器提供的模板方法

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

    二、 自定义锁

    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();
        }
    }
    
  • 相关阅读:
    handsontable合并项mergeCells应用及扩展
    handsontable的基础应用
    overflow的使用
    阿里云服务器磁盘空间扩容步骤
    使用Gitblit 在Windows2008 r2上部署Git Server(完整版)
    搭建一个基于微信公众号的信息采集功能
    js数组内置方法
    C#数组、js数组、json
    将EF项目从dbfirst转化为codefirst
    通过HttpWebRequest调用webService
  • 原文地址:https://www.cnblogs.com/jxkun/p/9374876.html
Copyright © 2011-2022 走看看