• Condition


    一、概述

     Condition就是维护一个条件队列,当AQS的线程在lock()内Condition.await()后,该线程会释放锁,然后进入Condition的条件队列,当别的线程Condition.signal()唤醒他后,他会进入AQS的同步队列等待获得锁

    核心方法:await()、signal()、signalAll()

    二、源码

    1、接口

    public interface Condition {
        //当前线程在接到信号或中断之前一直处于等待状态
        void await() throws InterruptedException;
        //当前线程在接到信号或中断之前一直处于等待状态,如果超时则返回false
        boolean await(long time, TimeUnit unit) throws InterruptedException;
        //当前线程在接到信号或中断之前一直处于等待状态,如果超时则返回-1,没超时就返回剩余的等待时间
        long awaitNanos(long nanosTimeout) throws InterruptedException;
        //当前线程在接到信号或中断之前一直处于等待状态,如果超过最后期限则返回false
        boolean awaitUntil(Date deadline) throws InterruptedException;
        //无法中断的等待
        void awaitUninterruptibly();
        //唤醒一个等待线程,线程必须先获得锁
        void signal();
        //唤醒所有等待线程,能返回的线程必须获取相关的锁
        void signalAll();
    }
    

    2、属性

    //队列的首节点
    private transient Node firstWaiter;
    //队列的尾节点
    private transient Node lastWaiter;
    
    //代表线程是在 signal 后被中断的
    private static final int REINTERRUPT =  1;
    //代表线程是在 signal 前被中断的
    private static final int THROW_IE    = -1;
    

    3、私有方法

    //添加lastWaiter
    private Node addConditionWaiter() {
        Node t = lastWaiter;
        //如果lastWaiter是取消状态
        if (t != null && t.waitStatus != Node.CONDITION) {
            //向前清理取消状态的waiter
            unlinkCancelledWaiters();
            t = lastWaiter;
        }
        //创建新节点,作为lastWaiter
        Node node = new Node(Thread.currentThread(), Node.CONDITION);
        if (t == null)
            firstWaiter = node;
        else
            t.nextWaiter = node;
        lastWaiter = node;
        return node;
    }
    
    //向前清理取消状态的waiter
    private void unlinkCancelledWaiters() {
        Node t = firstWaiter;
        Node trail = null;
        while (t != null) {
            Node next = t.nextWaiter;
            if (t.waitStatus != Node.CONDITION) {
                t.nextWaiter = null;
                if (trail == null)
                    firstWaiter = next;
                else
                    trail.nextWaiter = next;
                if (next == null)
                    lastWaiter = trail;
            }
            else
                trail = t;
            t = next;
        }
    }
    
    //删除或者转移节点到同步队列中,直到获取的节点是不可取消节点,或者null
    private void doSignal(Node first) {
        do {
            if ( (firstWaiter = first.nextWaiter) == null)
                lastWaiter = null;
            first.nextWaiter = null;
            //将节点从条件队列转到同步队列
        } while (!transferForSignal(first) && (first = firstWaiter) != null);
    }
    
    //移动所有节点到同步列表中
    private void doSignalAll(Node first) {
        lastWaiter = firstWaiter = null;
        do {
            Node next = first.nextWaiter;
            first.nextWaiter = null;
            transferForSignal(first);
            first = next;
        } while (first != null);
    }
    
    //确认线程的中断情况
    private int checkInterruptWhileWaiting(Node node) {
        return Thread.interrupted() ? (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) : 0;
    }
    
    //根据interruptMode来确定是应该抛出InterruptedException还是继续中断
    private void reportInterruptAfterWait(int interruptMode)
        throws InterruptedException {
        if (interruptMode == THROW_IE)
            throw new InterruptedException();
        else if (interruptMode == REINTERRUPT)
            selfInterrupt();
    }
    

      

    4、公共方法

    public ConditionObject() { }
    
    public final void signal() {
        //只有用到condition才需要实现,判断当前线程是否获得独占锁
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        Node first = firstWaiter;
        if (first != null)
            //唤醒节点
            doSignal(first);
    }
    
    public final void signalAll() {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        Node first = firstWaiter;
        if (first != null)
            //唤醒所有节点
            doSignalAll(first);
    }
    
    public final void awaitUninterruptibly() {
        Node node = addConditionWaiter();
        int savedState = fullyRelease(node);
        boolean interrupted = false;
        while (!isOnSyncQueue(node)) {
            LockSupport.park(this);
            if (Thread.interrupted())
                interrupted = true;
        }
        if (acquireQueued(node, savedState) || interrupted)
            selfInterrupt();
    }
    
    public final void await() throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        Node node = addConditionWaiter();
        //放弃所有持有的锁
        int savedState = fullyRelease(node);
        int interruptMode = 0;
        //阻塞判断,当前node是不是在同步队列时,不在同步队列那么就park当前线程
        while (!isOnSyncQueue(node)) {
            LockSupport.park(this);
            //如果被中断了,则检测中断
            if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                break;
        }
        //这是此节点已经在同步队列中了
        //在队列中获取锁,并判断当前的interruptMode不为-1,即不是抛出异常
        if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
            //把中断类型设置为,重新中断,意味在线程获得锁的时候,重新中断线程
            interruptMode = REINTERRUPT;
        if (node.nextWaiter != null) // clean up if cancelled
            unlinkCancelledWaiters();
        if (interruptMode != 0)
            reportInterruptAfterWait(interruptMode);
    }
    
    public final long awaitNanos(long nanosTimeout) throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        Node node = addConditionWaiter();
        int savedState = fullyRelease(node);
        final long deadline = System.nanoTime() + nanosTimeout;
        int interruptMode = 0;
        while (!isOnSyncQueue(node)) {
            if (nanosTimeout <= 0L) {
                transferAfterCancelledWait(node);
                break;
            }
            if (nanosTimeout >= spinForTimeoutThreshold)
                LockSupport.parkNanos(this, nanosTimeout);
            if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                break;
            nanosTimeout = deadline - System.nanoTime();
        }
        if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
            interruptMode = REINTERRUPT;
        if (node.nextWaiter != null)
            unlinkCancelledWaiters();
        if (interruptMode != 0)
            reportInterruptAfterWait(interruptMode);
        return deadline - System.nanoTime();
    }
    
    public final boolean awaitUntil(Date deadline) throws InterruptedException {
        long abstime = deadline.getTime();
        if (Thread.interrupted())
            throw new InterruptedException();
        Node node = addConditionWaiter();
        int savedState = fullyRelease(node);
        boolean timedout = false;
        int interruptMode = 0;
        while (!isOnSyncQueue(node)) {
            if (System.currentTimeMillis() > abstime) {
                timedout = transferAfterCancelledWait(node);
                break;
            }
            LockSupport.parkUntil(this, abstime);
            if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                break;
        }
        if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
            interruptMode = REINTERRUPT;
        if (node.nextWaiter != null)
            unlinkCancelledWaiters();
        if (interruptMode != 0)
            reportInterruptAfterWait(interruptMode);
        return !timedout;
    }
    
    public final boolean await(long time, TimeUnit unit)
            throws InterruptedException {
        long nanosTimeout = unit.toNanos(time);
        if (Thread.interrupted())
            throw new InterruptedException();
        Node node = addConditionWaiter();
        int savedState = fullyRelease(node);
        final long deadline = System.nanoTime() + nanosTimeout;
        boolean timedout = false;
        int interruptMode = 0;
        while (!isOnSyncQueue(node)) {
            if (nanosTimeout <= 0L) {
                timedout = transferAfterCancelledWait(node);
                break;
            }
            if (nanosTimeout >= spinForTimeoutThreshold)
                LockSupport.parkNanos(this, nanosTimeout);
            if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                break;
            nanosTimeout = deadline - System.nanoTime();
        }
        if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
            interruptMode = REINTERRUPT;
        if (node.nextWaiter != null)
            unlinkCancelledWaiters();
        if (interruptMode != 0)
            reportInterruptAfterWait(interruptMode);
        return !timedout;
    }
    

      

    5、辅助方法

    final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {
        return sync == AbstractQueuedSynchronizer.this;
    }
    
    protected final boolean hasWaiters() {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
            if (w.waitStatus == Node.CONDITION)
                return true;
        }
        return false;
    }
    
    protected final int getWaitQueueLength() {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        int n = 0;
        for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
            if (w.waitStatus == Node.CONDITION)
                ++n;
        }
        return n;
    }
    
    protected final Collection<Thread> getWaitingThreads() {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        ArrayList<Thread> list = new ArrayList<Thread>();
        for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
            if (w.waitStatus == Node.CONDITION) {
                Thread t = w.thread;
                if (t != null)
                    list.add(t);
            }
        }
        return list;
    }
    

      

  • 相关阅读:
    postgresql 修改配置,允许外部访问
    geopandas 把 shp 文件入库到 postgis 数据库
    geopandas 生成 geojson 文件
    geopandas 生成 shp 文件
    STM32 FSMC LCD 液晶的驱动—ILI9320
    SSTV简介+常用频率表+工作原理
    CasRel 一种新的用于关系三重抽取的级联二进制标记框架
    JAVA类在JVM加载过程
    20201320第三周学习笔记
    20201320第四周学习笔记
  • 原文地址:https://www.cnblogs.com/ctxsdhy/p/12446254.html
Copyright © 2020-2023  润新知