任意一个Java对象都有一级监视器方法,像wait(),notify()等,这些方法需要与synchronized配合使用可以实现等待通知功能。类似的Condition也提供了相应的方法。
Condition作为一个接口,只定义了一些模板方法,实现都在AbstractQueuedSynchronizer的内部类ConditionObject里。下面是Condition里的方法:
简要说明
在调用上面的方法之前,需要先获取到Condition关联的锁。
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
当调用await()方法后,当前线程会释放锁并等待,而其它线程调用Condition对象的signal()方法,通知当前线程后,当前线程获取到锁后会从await()方法返回。
换句话解释就是获得锁的线程发现某个条件不满足而不能继续执行,而且该条件需要其它线程对共享资源进行操作才能触发,所以必须释放锁。
实现分析
- 等待队列
在conditionObject对象里维护着一个FIFO的等待队列,队列中每个节点都包含了一个线程引用,该线程就是在condition对象上等待的线程。
一个condition包含一个等待队列,condition拥有首节点(firstWaiter)和尾节点(lastWaiter),当线程调用了await()方法后,将会以当前线程构造一个节点加入到队列的尾部。
在Object监视器模式下,一个对象拥有一个同步队列和一个等待队列,而Lock同步器拥有一个同步队列和多个等待队列。
等待
当调用了await()方法后,会使用当前线程进入等待队列并释放锁,同时线程状态变为等待状态。当从await()返回时,当前线程一定是获取到了锁。
通知
当调用了signal()方法后,只有在当前线程获取了锁之后,会唤醒在等待队列中等待时间最长的节点(首节点),在唤醒节点之前,节点会被移到同步队列并使用LockSupport唤醒节点中的线程。
Condition里的signalAll()方法,相当于对等待队列中的每个节点都执行一次signal()方法,将等待队列中所有节点全部移到同步队列中,并唤醒每个节点的线程。
使用场景
使用Condition可以实现等待通知模式,一些特殊的等待队列等。 阻塞队列底层就是使用了Condition的等待通知模式来实现的:当往一个已满的队列里添加元素时此时线程会被阻塞;当队列已空再从中取元素时线程也会被阻塞。
源码分析可以看这篇文章:源码分析:②ReentrantLock之条件锁Condition
参考文章:《Java并发编程的艺术》
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。