AQS抽象队列同步器

依弗布德甘 · · 775 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

模板方法模式

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。 模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤

Lock接口及其实现 中,DemoReentrantLock 和 DemoReadWriteLock 代码相似度很高。DemoReentrantLock 中的加解锁完全可以用DemoReadWriteLock中代替,即可实现加解锁。

优化两个锁的代码-采用模板方法模式

  • CommonMask实现两个锁共有的方法
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;

public class CommonMask {
    AtomicInteger readCount = new AtomicInteger(0);
    AtomicInteger writeCount = new AtomicInteger(0);

    //独占锁 拥有者
    AtomicReference<Thread> owner = new AtomicReference<>();

    //等待队列    在JDK,队列是用链表实现的,但是作用是一样的
    public volatile LinkedBlockingQueue<WaitNode> waiters = new LinkedBlockingQueue<WaitNode>();
    class WaitNode{
        int type = 0;   //0 为想获取独占锁的线程,  1为想获取共享锁的线程
        Thread thread = null;
        int arg = 0;

        public WaitNode(Thread thread, int type, int arg){
            this.thread = thread;
            this.type = type;
            this.arg = arg;
        }
    }


    //这些业务逻辑,就是帮助我们进行排队
    //普通的队列,知识资源的片段,线程并不会阻塞
    //让线程排队,就需要这些公共的业务逻辑,抽出来了作为模板

    //获取独占锁
    public void lock() {
        int arg = 1;
        //尝试获取独占锁,若成功,退出方法,    若失败...
        if (!tryLock(arg)){
            //标记为独占锁
            WaitNode waitNode = new WaitNode(Thread.currentThread(), 0, arg);
            waiters.offer(waitNode);    //进入等待队列

            //循环尝试拿锁
            for(;;){
                //若队列头部是当前线程
                WaitNode head = waiters.peek();
                if (head!=null && head.thread == Thread.currentThread()){
                    if (!tryLock(arg)){      //再次尝试获取 独占锁
                        LockSupport.park();     //若失败,挂起线程
                    } else{     //若成功获取
                        waiters.poll();     //  将当前线程从队列头部移除
                        return;         //并退出方法
                    }
                }else{  //若不是队列头部元素
                    LockSupport.park();     //将当前线程挂起
                }
            }
        }
    }

    //释放独占锁
    public boolean unlock() {
        int arg = 1;

        //尝试释放独占锁 若失败返回true,若失败...
        if(tryUnlock(arg)){
            WaitNode next = waiters.peek(); //取出队列头部的元素
            if (next !=null){
                Thread th = next.thread;
                LockSupport.unpark(th);     //唤醒队列头部的线程
            }
            return true;                //返回true
        }
        return false;
    }

    //获取共享锁
    public void lockShared() {
        int arg = 1;

        if (tryLockShared(arg) < 0){    //如果tryAcquireShare失败
            //将当前进程放入队列
            WaitNode node = new WaitNode(Thread.currentThread(), 1, arg);
            waiters.offer(node);  //加入队列

            for (;;){
                //若队列头部的元素是当前线程
                WaitNode head = waiters.peek();
                if (head!=null && head.thread == Thread.currentThread()){
                    if (tryLockShared(arg) >=0){    //尝试获取共享锁,  若成功
                        waiters.poll();      //将当前线程从队列中移除

                        WaitNode next = waiters.peek();
                        if (next!=null && next.type==1){    //如果下一个线程也是等待共享锁
                            LockSupport.unpark(next.thread);    //将其唤醒
                        }
                        return;     //退出方法
                    }else{                      //若尝试失败
                        LockSupport.park();     //挂起线程
                    }
                }else{  //若不是头部元素
                    LockSupport.park();
                }

            }
        }
    }

    //解锁共享锁
    public boolean unLockShared() {
        int arg = 1;

        if (tryUnLockShared(arg)){     //当read count变为0,才叫release share成功
            WaitNode next = waiters.peek();
            if (next!=null){
                LockSupport.unpark(next.thread);
            }
            return true;
        }
        return false;
    }



    //留白,以下不是公共的逻辑,需要各自实现

    //尝试获取独占锁
    public boolean tryLock(int acquires) {
        throw new UnsupportedOperationException();
    }

    //尝试释放独占锁
    public boolean tryUnlock(int releases) {
        throw new UnsupportedOperationException();
    }

    //尝试获取共享锁
    public int tryLockShared(int acquires) {
        throw new UnsupportedOperationException();
    }

    //尝试解锁共享锁
    public boolean tryUnLockShared(int releases) {
        throw new UnsupportedOperationException();
    }

}

  • ReentrantLock与ReadWriteLock
public class DemoReentrantLock{
    private boolean isFair;
    public ReentrantLock(boolean isFair){
        this.isFair = isFair;
    }

    CommonMask mask = new CommonMask(){

        public boolean tryLock(int acquires){
            if (isFair){
                return tryFairLock(acquires);
            }else{
                return tryNonFairLock(acquires);
            }
        }

        public boolean tryFairLock(int acquires ){
            //如果read count !=0 返回false
            if (readCount.get() !=0)
                return false;

            int wct = writeCount.get();     //拿到 独占锁 当前状态

            if (wct==0){
                //判断一下,如果为队列头不,才做CAS操作,抢锁
                //try开头的这些方法,其实并不是公共的逻辑
                //他们经常会被修改
                WaitNode head = mask.waiters.peek();
                if (head!=null && head.thread==Thread.currentThread()&&
                        writeCount.compareAndSet(wct, wct + acquires)){     //通过修改state来抢锁
                    owner.set(Thread.currentThread());  //  抢到锁后,直接修改owner为当前线程
                    return true;
                }
            }else if (owner.get() == Thread.currentThread()){
                writeCount.set(wct + acquires);     //修改count值
                return true;
            }

            return false;
        }

        //不公平
        public boolean tryNonFairLock(int acquires) {
            //如果read count !=0 返回false
            if (readCount.get() !=0)
                return false;

            int wct = writeCount.get();     //拿到 独占锁 当前状态

            if (wct==0){
                //判断一下,如果为队列头不,才做CAS操作,抢锁
                //try开头的这些方法,其实并不是公共的逻辑
                //他们经常会被修改
                if (writeCount.compareAndSet(wct, wct + acquires)){     //通过修改state来抢锁
                    owner.set(Thread.currentThread());  //  抢到锁后,直接修改owner为当前线程
                    return true;
                }
            }else if (owner.get() == Thread.currentThread()){
                writeCount.set(wct + acquires);     //修改count值
                return true;
            }
            return false;
        }

        //尝试释放独占锁
        public boolean tryUnlock(int releases) {
            //若当前线程没有 持有独占锁
            if(owner.get()!= Thread.currentThread()){
                throw new IllegalMonitorStateException();       //抛IllegalMonitorStateException
            }
            int wc= writeCount.get();
            int nextc = wc - releases;      //计算 独占锁剩余占用
            writeCount.set(nextc);      //不管是否完全释放,都更新count值
            if (nextc==0){  //是否完全释放
                owner.compareAndSet(Thread.currentThread(), null);
                return true;
            }else{
                return false;
            }
        }
    };

    public void lock(){
        mask.lock();
    }

    public boolean tryLock(){
        return mask.tryLock(1);
    }

    public void unlock(){
        mask.unlock();
    }
}

public class DemoReadWriteLock {
    CommonMask mask = new CommonMask(){
        //尝试获取独占锁
        public boolean tryLock(int acquires) {
            //如果read count !=0 返回false
            if (readCount.get() !=0){
                return false;
            }
            int wct = writeCount.get();     //拿到 独占锁 当前状态
            if (wct==0){
                //判断一下,如果为队列头不,才做CAS操作,抢锁
                //try开头的这些方法,其实并不是公共的逻辑
                //他们经常会被修改
                if (writeCount.compareAndSet(wct, wct + acquires)){     //通过修改state来抢锁
                    owner.set(Thread.currentThread());  //  抢到锁后,直接修改owner为当前线程
                    return true;
                }
            }else if (owner.get() == Thread.currentThread()){
                writeCount.set(wct + acquires);     //修改count值
                return true;
            }
            return false;
        }

        //尝试释放独占锁
        public boolean tryUnlock(int releases) {
            //若当前线程没有 持有独占锁
            if(owner.get()!= Thread.currentThread()){
                throw new IllegalMonitorStateException();       //抛IllegalMonitorStateException
            }
            int wc= writeCount.get();
            int nextc = wc - releases;      //计算 独占锁剩余占用
            writeCount.set(nextc);      //不管是否完全释放,都更新count值
            if (nextc==0){  //是否完全释放
                owner.compareAndSet(Thread.currentThread(), null);
                return true;
            }else{
                return false;
            }
        }

        //尝试获取共享锁
        public int tryLockShared(int acquires) {
            while(true){
                if (writeCount.get()!=0 && owner.get() != Thread.currentThread()){
                    return -1;
                }
                int rct = readCount.get();
                if (readCount.compareAndSet(rct, rct + acquires)){
                    return 1;
                }
            }
        }

        //尝试解锁共享锁
        public boolean tryUnLockShared(int releases) {
            while(true){
                int rc = readCount.get();
                int nextc = rc - releases;
                if (readCount.compareAndSet(rc, nextc)){
                    return nextc==0;
                }
            }
        }
    };

    public void lock(){
        mask.lock();
    }

    public boolean tryLock(){
        return mask.tryLock(1);
    }

    public void unlock(){
        mask.unlock();
    } 

    public void lockShared(){
        mask.lockShared();
    }

    public boolean tryLockShared(){
        return mask.tryLockShared(1)==1;
    }

    public void unLockShared(){
        mask.unLockShared();
    } 

}


AQS(Abstract Queued Synchronizer)

  • AQS全称Abstract Queued Synchronizer(抽象队列同步器),是JAVA高并发核心类
  • AQS定义两种资源共享方式:Exclusive(独占,只有一个线程能执行,如ReentrantLock)和Share(共享,多个线程可同时执行,如Semaphore/CountDownLatch)

原理解析

aqs
  • 上述DemoReadWriteLock中描述的是有两个状态来记录读线程与写线程的count值,然而实际的ReadWriteLock并不是两个值,而是一个只有一个状态值,AQS字段state来记录线程状态

  • 字段state,state采用10进制转2进制的存储方式来表示当前对象的状态信息

二进制 十进制 readCount writCount
0000 0000 0000 0000 0000 0000 0000 0000 0 0 0
0000 0000 0000 0001 0000 0000 0000 0000 65536 1 0
0000 0000 0000 0010 0000 0000 0000 0000 131072 2 0
0000 0000 0000 0011 0000 0000 0000 0000 196608 3 0
0000 0000 0000 0000 0000 0000 0000 0001 1 0 1
0000 0000 0000 0001 0000 0000 0000 0001 65537 1 1

转换二进制后分为两步份来识别,前面一部分表示读的记录,后面的标识写的记录数

特性:

  • 阻塞等待队列
  • 共享/独占
  • 公平/非公平
  • 可重入
  • 允许中断

基于AQS的同步工具:

  • ReentrantLock(可重入锁)
  • ReentrantReadWriteLock(可重入的读写锁)
  • Semaphore(信号量) [基本上所有语言都有]
  • CountDownLatch(技术插销) 类比golang waitGroups
  • FutureTask(未来任务)
  • SynchronousQueues(同步队列集)

以上CommonMask就是一个简化的AQS

  • 其中tryLock、tryUnlock、 tryLockShared、 tryUnLockShared 分别对应AbstractQueuedSynchronizer中的
// 尝试获取 独占锁
protected boolean tryAcquire(int arg) {
        throw new UnsupportedOperationException();
}
// 尝试释放 独占锁
protected boolean tryRelease(int arg) {
        throw new UnsupportedOperationException();
}
//尝试获取 共享锁
protected int tryAcquireShared(int arg) {
        throw new UnsupportedOperationException();
}
//尝试释放 共享锁
protected boolean tryReleaseShared(int arg) {
        throw new UnsupportedOperationException();
}
  • lock、unLock、lockShared、unLockShared分别对应AbstractQueuedSynchronizer中的
// 加锁 独占锁
public final void acquire(int arg) {
    //...
}
// 解锁 独占锁
public final boolean release(int arg) {
    //...   
}
// 加锁 共享锁
public final void acquireShared(int arg) {
    //... 
}
// 解锁 共享锁
public final boolean releaseShared(int arg) {
    //...  
}

AbstractQueuedSynchronizer源码注释

/**
 * Provides a framework for implementing blocking locks and related synchronizers  
 * (semaphores, events, etc) that rely on first-in-first-out (FIFO) wait queues.  
 * 提供了一个实现阻塞式锁 及相关的 依赖于先进先出等待队列的 同步器(如信号量, 事件...) 的框架。
 *
 * This class is designed to be a useful basis for most kinds of synchronizers that rely on 
 * a single atomic {@code int} value to represent state.
 * 该类被设计为 所有依赖于单个原子性值 来代表其状态的同步器 的基石。
 *
 * Subclasses must define the protected methods that change this state, and which
 * define what that state means in terms of this object being acquired or released.  
 * 子类必须 通过定义 protected 方法 来改变 此状态, 并且 定义 定义该状态意味着 当前对象 被 获取了   
 * 或 被释放了。
 *
 * Given these, the other methods in this class carryout all queuing and blocking mechanics. 
 * 基于上述已知, 此类中的其他方法 实行了 所有的 队列等待 和 阻塞 机制。
 *
 * Subclasses can maintain other state fields, but only the atomically updated {@code int}
 * value manipulated using methods {@link #getState}, {@link #setState} and {@link 
 * #compareAndSetState} is tracked with respect to synchronization.
 * 子类可以维持其他状态域, 但是只有 被 getState, setState 和 compareAndSetState(CAS 比较并设置
 * 转态) 方法 管理的 且 被原子性 更新地 值 才会被同步化关联
 *
 * <p>Subclasses should be defined as non-public internal helper classes that are used to 
 * implement the synchronization properties of their enclosing class. 
 * 子类 应当被定义为 被用于实现它们的 封闭类 的 同步特性 的 非公开帮助类
 *
 * Class {@code AbstractQueuedSynchronizer} does not implement any synchronization 
 * interface.  
 * AQS 并没有实现任何同步接口。
 *
 * Instead it defines methods such as {@link #acquireInterruptibly} that can be invoked as
 * appropriate by concrete locks and related synchronizers to implement their public 
 * methods.
 * 它定义了诸如 acquireInterruptibly 等 可以 被 具体的锁 和 相关的同步器 请求 来实现 它们的公有方
 * 法
 *
 * <p>This class supports either or both a default <em>exclusive</em> mode and a 
 * <em>shared</em> mode. 
 * 该类支持 仅排除(排他)模式, 仅共享模式 以及 两种模式并存。
 *
 *
 * When acquired in exclusive mode, attempted acquires by other threads cannot succeed. 
 * 当一个线程 在 排他模式中 获取了锁, 其他线程的 获取(该锁) 就不能成功
 *
 * Shared mode acquires by multiple threads may (but need not) succeed. 
 * 共享模式下, 多个线程获取 一个锁 可能成功(但是 通常 不需要)
 *
 * This class does not &quot;understand&quot; these differences except in the mechanical 
 * sense that when a shared mode acquire succeeds, the next waiting thread (if 
 * one exists) must also determine whether it can acquire as well. 
 * 该类只有在 一个线程在共享模式下获取到了锁 才会 去判断 下一个线程是否能够获取该锁
 *
 * Threads waiting in the different modes share the same FIFO queue. 
 * 在不同模式下等待的线程 共享 先进先出队列
 *
 * Usually, implementation subclasses support only one of these modes, but both can come 
 * into play for example in a {@link ReadWriteLock}. 
 * 通常, 实现该抽象类的子类 只支持其中一种模式(共享, 排他), 但是 在 读写锁中 两种模式可以并存。
 *
 * Subclasses that support only exclusive or only shared modes need not define the methods 
 * supporting the unused mode.
 * 仅支持排他 或 仅支持共享 模式的子类 不需要定义 未被使用的 模式的方法
 *
 * <p>This class defines a nested {@link ConditionObject} class that
 * can be used as a {@link Condition} implementation by subclasses
 * supporting exclusive mode for which method {@link #isHeldExclusively} reports whether 
 * synchronization is exclusively held with respect to the current thread, method {@link 
 * #release} invoked with the current {@link #getState} value fully releases
 * this object, and {@link #acquire}, given this saved state value,
 * eventually restores this object to its previous acquired state. 
 * 该类定义了一个可被用作 支持排他模式的子类的状态应用 的 嵌套类。isHeldExclusively 方法 报告了
 * 同步对当前线程是否维持排他模式。release 方法 通过 getState请求当前 线程状态值, 并且充分释放该对
 * 象。acquire方法 根据已保存的状态值 最终 将该对象恢复到 它 上次被 获取之前的状态。
 *  衍生: semaphore(信号量) 中的 acquire, release
 *
 * No {@code AbstractQueuedSynchronizer} method otherwise creates such a
 * condition, so if this constraint cannot be met, do not use it.  
 * 没有抽象队列同步器 方法 就只好 创建 创建一个 状态, 如果这些约束不满足, 就不使用它
 *
 * The behavior of {@link ConditionObject} depends of course on the
 * semantics of its synchronizer implementation.
 * 状态对象 的行为 毫无疑问 取决于 它的 同步器应用 的 语义
 *
 * <p>This class provides inspection, instrumentation, and monitoring
 * methods for the internal queue, as well as similar methods for
 * condition objects. 
 * 该类对内部队列 以及相似的 状态对象 提供了 检查, 仪器化 和 监控 的方法
 *
 * These can be exported as desired into classes using an {@code AbstractQueuedSynchronizer} 
 * for their synchronization mechanics.
 * 这些方法可以根据需求 通过 AQS 来 导入 到 类中 以实现同步机制
 *
 * <p>Serialization of this class stores only the underlying atomic
 * integer maintaining state, so deserialized objects have empty
 * thread queues. 
 * 此类的序列化仅存储原子性的 整形 维持 状态, 所以
 *
 * Typical subclasses requiring serializability will define a {@code readObject} method that 
 * restores this to a known initial state upon deserialization.
 * 典型的需要序列化属性的 子类会通过 定义 一个 读取 对象的 方法 来将它 恢复为 取决于 反序列化的 已 
 * 知的的 初始状态 
 *
 * <h3>Usage</h3>
 *
 * <p>To use this class as the basis of a synchronizer, redefine the
 * following methods, as applicable, by inspecting and/or modifying
 * the synchronization state using {@link #getState}, {@link
 * #setState} and/or {@link #compareAndSetState}:
 * 要使用该类作为同步器的基础, 需要通过 使用 getState, setState, CAS 方法 来 检查 或 修改 重定义以下方法为 可执行的 方法。
 *
 * <ul>
 * <li> {@link #tryAcquire}
 * <li> {@link #tryRelease}
 * <li> {@link #tryAcquireShared}
 * <li> {@link #tryReleaseShared}
 * <li> {@link #isHeldExclusively}
 * </ul>
 *
 * Each of these methods by default throws {@link UnsupportedOperationException}. 
 * 以上每个方法都会默认抛出 不支持的操作选项 异常
 *
 * Implementations of these methods must be internally thread-safe, and should in general be 
 * short and not block.
 * 这些方法 的实现类 必须是 内部 线程 安全的m 并且普遍应当 量小 且 非阻塞
 *
 * Defining these methods is the <em>only</em> supported means of using this class. 
 * 以上这些方法 的 定义 仅用于 支持 该类
 *
 * All other methods are declared {@code final} because they cannot be independently varied.
 * 其他的方法都以 final 声明, 因为它们 不能是 无关变化的
 *
 * <p>You may also find the inherited methods from {@link AbstractOwnableSynchronizer} 
 * useful to keep track of the thread owning an exclusive synchronizer. 
 * 你可能也会发现 从 AQS 继承来的 方法 在追踪 一个 拥有 排他模式 同步器的 线程时 很 有用
 *
 * You are encouraged to use them -- this enables monitoring and diagnostic tools to assist 
 * users in determining which threads hold locks.
 * 使用他们 使得 负责监控 和 诊断的工具 能更好地 帮助用户确定 哪个线程占用着锁
 *
 * <p>Even though this class is based on an internal FIFO queue, it does not automatically  
 * enforce FIFO acquisition policies.  
 * 尽管该类 基于 一个 内部的 先进先出 队列, 他并没有 自动 强迫 使用 先进先出 的获取策略
 *
 * The core of exclusive synchronization takes the form:
 * 排他同步的核心为以下形式:
 * <pre>
 * Acquire:
 *      // 只要没有获取到参数
 *     while (!tryAcquire(arg)) {
 *        // 如果线程没有入队, 就让他入队
 *        <em>enqueue thread if it is not already queued</em>;
 *        // 也可能是当前线程被阻塞了
 *        <em>possibly block current thread</em>;
 *     }
 *
 * Release:
 *     // 如果释放参数成功
 *     if (tryRelease(arg))
 *        // 就解除队列头部的线程
 *        <em>unblock the first queued thread</em>;
 * </pre>
 *
 * (Shared mode is similar but may involve cascading signals.)
 * 共享模式也相似, 但是可能涉及 层级信号
 *
 * <p id="barging">Because checks in acquire are invoked before
 * enqueuing, a newly acquiring thread may <em>barge</em> ahead of
 * others that are blocked and queued.  
 * 因为在线程入队前需要请求检查, 一个新 获取的线程 可能 会 冲撞 到其他 阻塞 且处于 队列中的 线程(即
 * 插队) [非公平锁]
 *
 * However, you can, if desired, define {@code tryAcquire} and/or {@code tryAcquireShared} 
 * to disable barging by internally invoking one or more of the inspection
 * methods, thereby providing a <em>fair</em> FIFO acquisition order.
 * 有需求的话 也可以 在 tryAcquire 和/或 tryAcquireShared中 通过内部请求来 禁用 冲撞参数, 从而
 * 提供一个公平的 先进先出 获取顺序 [公平锁]
 *
 * In particular, most fair synchronizers can define {@code tryAcquire}
 * to return {@code false} if {@link #hasQueuedPredecessors} (a method
 * specifically designed to be used by fair synchronizers) returns
 * {@code true}.  Other variations are possible.
 * 事实上, 更公平的同步器可以定义 tryAcquire 方法 返回 false 如果队列中有前者(这是一个被特定用于定
 * 义公平同步器 的设计), 如果队列中没有前者就返回true 
 *
 * <p>Throughput and scalability are generally highest for the default barging (also known 
 * as <em>greedy</em>,<em>renouncement</em>, and <em>convoy-avoidance</em>) strategy.
 * 尽管默认使用 barging 机制 的 写入 和 可扩展性 (又称贪婪重申 避免护航) 是最高的。
 *
 * While this is not guaranteed to be fair or starvation-free, earlier
 * queued threads are allowed to recontend before later queued
 * threads, and each recontention has an unbiased chance to succeed
 * against incoming threads.  
 * 尽管这并没有保证 公平 或者说 无饥饿性, 更早入队的线程 被允许 在 后入队的线程 之后 重申 使用权, 
 * 每次重申都有 公平的 成功机会。
 *
 * Also, while acquires do not &quot;spin&quot; in the usual sense, they may perform 
 * multiple invocations of {@code tryAcquire} interspersed with other
 * computations before blocking.
 * 尽管 请求 并不会自旋, 通常 它们 会执行许多次 tryAcquire 方法调用,在阻塞之前, 其间夹杂着其他的
 * 计算
 *
 * This gives most of the benefits of spins when exclusive synchronization is only briefly   
 * held, without most of the liabilities when it isn't. 
 * 当处于排他同步模式时, 它具有了所有自旋的好处, 而当不处于排他模式时, 就不需要这些义务
 *
 * If so desired, you can augment this by preceding calls to acquire methods with "fast-
 * path" checks, possibly prechecking {@link #hasContended} and/or {@link #hasQueuedThreads} 
 * to only do so if the synchronizer is likely not to be contended.
 *
 * <p>This class provides an efficient and scalable basis for
 * synchronization in part by specializing its range of use to
 * synchronizers that can rely on {@code int} state, acquire, and
 * release parameters, and an internal FIFO wait queue. When this does
 * not suffice, you can build synchronizers from a lower level using
 * {@link java.util.concurrent.atomic atomic} classes, your own custom
 * {@link java.util.Queue} classes, and {@link LockSupport} blocking
 * support.
 * 同步器 <-依赖于- state,  acquire,release param, 内部等待队列
 * 修改 同步器的使用范围  -> 扩展 和 效用
 * 可使用原子类, 队列类 和 LockSupport(提供阻塞, park, unpark) 自己构造同步器
 *
 * <h3>Usage Examples</h3>
 *
 * <p>Here is a non-reentrant mutual exclusion lock class that uses the value zero to 
 * represent the unlocked state, and one to represent the locked state.
 * 这是一个不可重入的互斥锁类, 0: 未获得锁 1: 已获得锁
 *
 * While a non-reentrant lock does not strictly require recording of the current owner
 * thread, this class does so anyway to make usage easier to monitor.
 * 尽管 一个 非可重入锁, 并不严格要求记录当前线程的所有者, 该类确实这么做了, 以使使用和监控更方便
 *
 * It also supports conditions and exposes one of the instrumentation methods:
 * 它还提供了状况 状态 和 暴露设备方法 的支持
 *
 *  <pre> {@code
 * class Mutex implements Lock, java.io.Serializable {
 *
 *   // Our internal helper class 内部帮助类
 *   private static class Sync extends AbstractQueuedSynchronizer {
 *     // Reports whether in locked state 报告是否在使用锁的状态
 *     protected boolean isHeldExclusively() {
 *       return getState() == 1;
 *     }
 *
 *     // Acquires the lock if state is zero 如果状态为0就获取锁
 *     public boolean tryAcquire(int acquires) {
 *       assert acquires == 1; // Otherwise unused
 *       // CAS
 *       if (compareAndSetState(0, 1)) {
 *         setExclusiveOwnerThread(Thread.currentThread());
 *         return true;
 *       }
 *       return false;
 *     }
 *
 *     // Releases the lock by setting state to zero 通过将状态设置为 0 来 释放锁
 *     protected boolean tryRelease(int releases) {
 *       assert releases == 1; // Otherwise unused
 *       if (getState() == 0) throw new IllegalMonitorStateException();
 *       setExclusiveOwnerThread(null);
 *       setState(0);
 *       return true;
 *     }
 *
 *     // Provides a Condition 提供状态
 *     Condition newCondition() { return new ConditionObject(); }
 *
 *     // Deserializes properly 适当的反序列化
 *     private void readObject(ObjectInputStream s)
 *         throws IOException, ClassNotFoundException {
 *       s.defaultReadObject();
 *       setState(0); // reset to unlocked state 重设
 *     }
 *   }
 *
 *   // The sync object does all the hard work. We just forward to it.
 *   // 同步对象 做了 所有的 苦工
 *   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));
 *   }
 * }}</pre>
 *
 * <p>Here is a latch class that is like a {@link java.util.concurrent.CountDownLatch 
 * CountDownLatch} except that it only requires a single {@code signal} to
 * fire.
 * 类似CountDownLatch, 除了只需要 一个简单的信号 来启动
 *
 * Because a latch is non-exclusive, it uses the {@code shared}
 * acquire and release methods.
 * Latch 是非排他模式的, 使用共享模式的 获取 和 释放方法
 *
 *  <pre> {@code
 * class BooleanLatch {
 *
 *   private static class Sync extends AbstractQueuedSynchronizer {
 *     boolean isSignalled() { return getState() != 0; }
 *
 *     protected int tryAcquireShared(int ignore) {
 *       return isSignalled() ? 1 : -1;
 *     }
 *
 *     protected boolean tryReleaseShared(int ignore) {
 *       setState(1);
 *       return true;
 *     }
 *   }
 *
 *   private final Sync sync = new Sync();
 *   public boolean isSignalled() { return sync.isSignalled(); }
 *   public void signal()         { sync.releaseShared(1); }
 *   public void await() throws InterruptedException {
 *     sync.acquireSharedInterruptibly(1);
 *   }
 * }}</pre>
 *
 * @since 1.5
 * @author Doug Lea
 */

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:依弗布德甘

查看原文:AQS抽象队列同步器

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

775 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传