Java并发编程之Condition机制

Java并发编程之Condition机制

**引言:**Condition存在于Concurrent包中,主要用于替代以前对象Object上的wait()、notify()等方法实现线程间的协作。相比wait()、notify(),Condition根据和Lock的结合,可以实现更复杂和精细的线程协同和等待。从整体上来看Object的wait和notify/notifyAll是与对象监视器配合完成线程间的等待/通知机制,而Condition是与Lock配合完成等待通知机制,前者是java底层级别的,后者是语言级别的,具有更高的可控制性和扩展性。两者除了在使用方式上不同外,在功能特性上还是有很多的不同:
1、Condition能够支持不响应中断,而Object方式不支持。
2、Condition能够支持多个等待队列(new 多个Condition对象),而Object方式只能支持一个。
3、Condition能够支持超时时间的设置,而Object不支持。

**实现原理:**Condition是AQS的内部类。每个Condition对象都包含一个队列(等待队列Condition中拥有首节点firstWaiter和尾节点lastWaiter)。等待队列是一个FIFO的队列,在队列中的每个节点都包含了一个线程引用,该线程就是在Condition对象上等待的线程,如果一个线程调用了Condition.await()方法,那么该线程将会释放锁、构造成节点加入等待队列并进入等待状态。在Object的监视器模型上,一个对象拥有一个同步队列和一个等待队列,而并发包中的Lock拥有一个同步队列和多个等待队列。
在这里插入图片描述
Condition的主要方法:
1、await()方法:该方法有两个重载方法,分别是不带参数的await()方法和带超时时间的await()方法,调用该方法的线程是成功获取了锁的线程,也就是同步队列中的首节点,该方法会将当前线程构造节点并加入等待队列中,然后释放同步状态,唤醒同步队列中的后继节点,然后当前线程会进入等待状态。出现以下四种情况前,当前线程将一直处于休眠状态:
(1)、其他某个线程调用此 Condition 的 signal() 方法,并且碰巧将当前线程选为被唤醒的线程。
(2)、其他某个线程调用此 Condition 的 signalAll() 方法。
(3)、其他某个线程中断当前线程,且支持中断线程的挂起。
(4)、发生“虚假唤醒”。

 public final void await() throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();
            ConditionNode node = new ConditionNode();
            long savedState = enableWait(node);
            LockSupport.setCurrentBlocker(this); // for back-compatibility
            boolean interrupted = false, cancelled = false;
            while (!canReacquire(node)) {
                if (interrupted |= Thread.interrupted()) {
                    if (cancelled = (node.getAndUnsetStatus(COND) & COND) != 0)
                        break;              // else interrupted after signal
                } else if ((node.status & COND) != 0) {
                    try {
                        ForkJoinPool.managedBlock(node);
                    } catch (InterruptedException ie) {
                        interrupted = true;
                    }
                } else
                    Thread.onSpinWait();    // awoke while enqueuing
            }
            LockSupport.setCurrentBlocker(null);
            node.clearStatus();
            acquire(node, savedState, false, false, false, 0L);
            if (interrupted) {
                if (cancelled) {
                    unlinkCancelledWaiters(node);
                    throw new InterruptedException();
                }
                Thread.currentThread().interrupt();
            }
        }

   
     public final boolean await(long time, TimeUnit unit)
                throws InterruptedException {
            long nanosTimeout = unit.toNanos(time);
            if (Thread.interrupted())
                throw new InterruptedException();
            ConditionNode node = new ConditionNode();
            long savedState = enableWait(node);
            long nanos = (nanosTimeout < 0L) ? 0L : nanosTimeout;
            long deadline = System.nanoTime() + nanos;
            boolean cancelled = false, interrupted = false;
            while (!canReacquire(node)) {
                if ((interrupted |= Thread.interrupted()) ||
                    (nanos = deadline - System.nanoTime()) <= 0L) {
                    if (cancelled = (node.getAndUnsetStatus(COND) & COND) != 0)
                        break;
                } else
                    LockSupport.parkNanos(this, nanos);
            }
            node.clearStatus();
            acquire(node, savedState, false, false, false, 0L);
            if (cancelled) {
                unlinkCancelledWaiters(node);
                if (interrupted)
                    throw new InterruptedException();
            } else if (interrupted)
                Thread.currentThread().interrupt();
            return !cancelled;
        }

2、awaitUninterruptibly()方法:该方法同不带参数的await()作用一样,但是调用该方法的线程不响应中断。出现以下三种情况前,当前线程将一直处于休眠状态:
(1)、其他某个线程调用此 Condition 的 signal() 方法,并且碰巧将当前线程选为被唤醒的线程。
(2)、其他某个线程调用此 Condition 的 signalAll() 方法。
(3)、发生“虚假唤醒”。

 public final void awaitUninterruptibly() {
            ConditionNode node = new ConditionNode();
            long savedState = enableWait(node);
            LockSupport.setCurrentBlocker(this); // for back-compatibility
            boolean interrupted = false;
            while (!canReacquire(node)) {
                if (Thread.interrupted())
                    interrupted = true;
                else if ((node.status & COND) != 0) {
                    try {
                        ForkJoinPool.managedBlock(node);
                    } catch (InterruptedException ie) {
                        interrupted = true;
                    }
                } else
                    Thread.onSpinWait();    // awoke while enqueuing
            }
            LockSupport.setCurrentBlocker(null);
            node.clearStatus();
            acquire(node, savedState, false, false, false, 0L);
            if (interrupted)
                Thread.currentThread().interrupt();
        }

3、awaitNanos()方法:调用该方法的线程进入等待状态直到被通知、中断或者超时,返回值表示剩余超时时间。出现以下五种情况前,当前线程将一直处于休眠状态:
(1)、其他某个线程调用此 Condition 的 signal() 方法,并且碰巧将当前线程选为被唤醒的线程。
(2)、其他某个线程调用此 Condition 的 signalAll() 方法。
(3)、其他某个线程中断当前线程,且支持中断线程的挂起。
(4)、发生“虚假唤醒”。
(5)、已超过指定的等待时间。

    public final long awaitNanos(long nanosTimeout)
                throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();
            ConditionNode node = new ConditionNode();
            long savedState = enableWait(node);
            long nanos = (nanosTimeout < 0L) ? 0L : nanosTimeout;
            long deadline = System.nanoTime() + nanos;
            boolean cancelled = false, interrupted = false;
            while (!canReacquire(node)) {
                if ((interrupted |= Thread.interrupted()) ||
                    (nanos = deadline - System.nanoTime()) <= 0L) {
                    if (cancelled = (node.getAndUnsetStatus(COND) & COND) != 0)
                        break;
                } else
                    LockSupport.parkNanos(this, nanos);
            }
            node.clearStatus();
            acquire(node, savedState, false, false, false, 0L);
            if (cancelled) {
                unlinkCancelledWaiters(node);
                if (interrupted)
                    throw new InterruptedException();
            } else if (interrupted)
                Thread.currentThread().interrupt();
            long remaining = deadline - System.nanoTime(); // avoid overflow
            return (remaining <= nanosTimeout) ? remaining : Long.MIN_VALUE;
        }

4、awaitUntil()方法:调用该方法的线程进入等待状态直到被通知、中断或者到某个时间。如果没有到指定时间就被通知,方法返回true,否则,表示到了指定时间,返回false。出现以下五种情况前,当前线程将一直处于休眠状态:
(1)、其他某个线程调用此 Condition 的 signal() 方法,并且碰巧将当前线程选为被唤醒的线程。
(2)、其他某个线程调用此 Condition 的 signalAll() 方法。
(3)、其他某个线程中断当前线程,且支持中断线程的挂起。
(4)、发生“虚假唤醒”。
(5)、指定的最后期限到了。

 public final boolean awaitUntil(Date deadline)
                throws InterruptedException {
            long abstime = deadline.getTime();
            if (Thread.interrupted())
                throw new InterruptedException();
            ConditionNode node = new ConditionNode();
            long savedState = enableWait(node);
            boolean cancelled = false, interrupted = false;
            while (!canReacquire(node)) {
                if ((interrupted |= Thread.interrupted()) ||
                    System.currentTimeMillis() >= abstime) {
                    if (cancelled = (node.getAndUnsetStatus(COND) & COND) != 0)
                        break;
                } else
                    LockSupport.parkUntil(this, abstime);
            }
            node.clearStatus();
            acquire(node, savedState, false, false, false, 0L);
            if (cancelled) {
                unlinkCancelledWaiters(node);
                if (interrupted)
                    throw new InterruptedException();
            } else if (interrupted)
                Thread.currentThread().interrupt();
            return !cancelled;
        }

5、signal()方法:唤醒一个等待在Condition上的线程,该线程从等待方法返回前必须获得与Condition相关联的锁。

public final void signal() {
            ConditionNode first = firstWaiter;
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            if (first != null)
                doSignal(first, false);
        }

6、signalAll()方法:唤醒所有等待在Condition上的线程,能够从等待方法返回的线程必须获得与Condition相关联的锁。

public final void signalAll() {
            ConditionNode first = firstWaiter;
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            if (first != null)
                doSignal(first, true);
        }

本文参考
本文主要参考以下文章,谨以技术分享为目的,将此文搬到CSDN上,如有侵权问题请联系本人,乐于分享提高。
作者: DivineH
链接:https://blog.csdn.net/qq_38293564/article/details/80554516

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值