当前位置: 首页 > 后端技术 > Java

【JAVA并发编程】Condition简介

时间:2023-04-02 00:26:32 Java

一、Condition简介Java对象的wait()、notify()和notifyAll()方法,这些方法配合synchronized关键字实现wait/notify模式。Condition接口也提供了类似的功能,可以配合Lock实现等待/通知模式,但两者还是有一些区别的。对比项ObjectMoitorConditionPrecondition获取对象的锁调用Lock.lock()获取锁调用lock.newCondition()获取Condition调用方法object.wait()condition.await()等待队列数待多个当前线程释放锁并进入等待状态支持当前线程释放锁并进入等待状态,等待状态下响应中断不支持当前线程释放锁并进入timeoutwaitingstate支持当前线程释放锁进入等待状态,直到未来某个时间不支持唤醒等待队列中的一个线程支持唤醒等待队列中的所有线程功能的关键。2.1等待队列队列中的每个节点都包含一个线程引用,也就是等待Condition对象的线程。如果一个线程调用condition.await()方法,该线程会释放锁并构造节点加入等待队列尾部。同步队列和等待队列中的节点类型是同步器的静态内部类AbstractQueuedSynchronized.Node。等待队列的基本结构如图所示:2.2等待从队列的角度来看await()方法,调用await()方法时,相当于移动了同步队列的第一个节点(当前获取锁的线程)到Condition等待队列的末尾。但实际上同步队列的第一个节点并不会直接加入到等待队列中,而是通过addConditionWaiter()方法将当前线程构造为一个新的节点加入到等待队列中。代码如下:publicfinalvoidawait()throwsInterruptedException{if(Thread.interrupted())thrownewInterruptedException();//构造一个新的Node节点,加入到等待队列的尾部Nodenode=addConditionWaiter();intsavedState=fullyRelease(node);中断模式=0;while(!isOnSyncQueue(node)){//挂起当前线程LockSupport.park(this);如果((interruptMode=checkInterruptWhileWaiting(节点))!=0)中断;}if(acquireQueued(node,savedState)&&interruptMode!=THROW_IE)interruptMode=REINTERRUPT;if(node.nextWaiter!=null)//如果取消则清理unlinkCancelledWaiters();if(interruptMode!=0)reportInterruptAfterWait(interruptMode)}2.3唤醒调用Condition的signal()方法会唤醒等待队列中等待时间最长的节点,即第一个节点。在唤醒节点之前,它会将节点移动到同步队列的末尾。publicfinalvoidsignal(){if(!isHeldExclusively())thrownewIllegalMonitorStateException();Nodefirst=firstWaiter;如果(第一个!=null)doSignal(第一个);}finalbooleantransferForSignal(Nodenode){if(!compareAndSetWaitStatus(node,Node.CONDITION,0))returnfalse;//将节点加到步队队列末端Nodep=enq(node);intws=p.waitStatus;如果(ws>0||!compareAndSetWaitStatus(p,ws,Node.SIGNAL))LockSupport.unpark(node.thread);返回真;}