Condition

来源:互联网 发布:wifi模块怎么传输数据 编辑:程序博客网 时间:2024/04/27 20:06

1、概述
任意一个Java对象都拥有一组监视器方法(定义在java.lang.Object上),主要包括wait()、wait(long timeout)、notify()以及notifyAll()方法,与synchronised同步关键字配合,可以实现等待/通知模式。

Condition接口也提供了类似Object的监视器方法,与Lock配合,也可以实现等待/通知模式。

主要区别:Object只有一个等待队列,Condition允许多个等待队列。

2、原理分析

ConditionObject是Condtion的实现类,也是AbstractQueuedSynchronizer的内部类。即Condition实现的是同步器的内部类,因此每个Condition的实例都能访问同步器方法。

Object的监视器模型,一个对象有一个同步队列和一个等待队列;
而同步器拥有一个同步队列和多个等待队列。

1)等待

public final void await() throws InterruptedException {    if (Thread.interrupted())        throw new InterruptedException();    Node node = addConditionWaiter();// 将当前线程进入等待队列    int savedState = fullyRelease(node);// 释放同步状态    int interruptMode = 0;    while (!isOnSyncQueue(node)) {        LockSupport.park(this);        if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)            break;    }    if (acquireQueued(node, savedState) && interruptMode != THROW_IE)        interruptMode = REINTERRUPT;    if (node.nextWaiter != null) // clean up if cancelled        unlinkCancelledWaiters();    if (interruptMode != 0)        reportInterruptAfterWait(interruptMode);}

调用await()方法,会使当前线程进入等待队列,并释放锁,线程状态变为等待状态。
从队列的角度看,相当于将同步队列的首节点移动到了Condition的等待队列中。

2)通知

public final void signal() {    // 判断当前线程是否获取了锁    if (!isHeldExclusively())        throw new IllegalMonitorStateException();    Node first = firstWaiter;    if (first != null)        doSignal(first);}

首先检查当前线程是否获取了锁,获取锁之后,则调用同步器的enq(Node node) 方法,将等待队列的首节点(等待队列中等待时间最长的点)线程安全地移动到同步队列中,并使用LockSupport唤醒节点中的线程。

唤醒之后,将从await()方法的while循环中退出,进而调用同步器的acquireQueued()方法,加入到获取同步状态的竞争中。

Condition的signalAll()方法,相当于等待队列中的每个节点执行一次signal()方法,效果就是将等待队列中的所有节点全部移到同步队列中,并唤醒每个节点的线程。

3、LockSupport工具类

LockSupport定义一组公共静态方法,如park()、unpark()等,提供最基本的线程阻塞和唤醒功能。

原创粉丝点击