概述
他是一个接口类。
演示例子
结合重入锁ReentrantLock:
1 | @Slf4j |
运行结果
1 | 09:39:54.468 [Thread-0] INFO com.mmall.concurrency.lock.LockExample6 - wait signal |
例子分析
- 可以看出输出的日志是与我们提到的执行顺序是对应的。
- 首先声明定义一个reentrantlock实例,并调用它的newCondition()创建一个condition实例并取出;
- 然后当线程1中调用reentrantLock.lock()后,就进入AQS的等待队列中,即之前介绍过的双向列表;
- 当调用condition.await()后,线程释放锁并从AQS等待队列中被移除,紧接着就被加入到Condition的等待队列中,该线程再次被唤醒则需要一个signal信号;
- 当线程1释放锁,线程2就被唤醒并尝试获取锁。获取后,也加入到AQS的等待队列中。通过调用condition.signalAll()给所有处于condition等待队列的线程发送信号,此时线程1又从Condition等待队列被移除,并加入到AQS等待队列中(还未唤醒)。最后线程2释放锁。
- 在线程2释放锁后,线程1拿到锁。此时线程1又处于AQS等待队列的head节点,则又被唤醒,接着上次执行到的地方继续执行后续操作。
源码分析
类内成员
源码大注释:
1 | /** |
注释重点:
- Condition使得每个对象,因都通过结合他们自己和随意锁的实现,且具有多个等待集合(wait-sets)而被区分开来,从而使监视器(monitor)方法失效。
- Conditions(被当做Condition队列)为场景提供一种新处理方式:一个线程可以暂停自己的执行,直到被另一个具有一些可能正确的状态信息的线程通知。由于共享的状态信息的访问发生在不同的线程间,因此它必须被某种形式的锁保护起来。
- 该类提供的关键属性是原子性地释放锁,并暂停当前线程。
- Condition的实例实际上是一个锁。如果为了一个锁机制而要获取一个Condition实例,需要使用它的newCondition()方法。
类内接口
1. await()
调用该方法会使线程等待直至线程被给予信号量或被中断。
2. await(long time, TimeUnit unit)
指定超时时间参数,或超时时间过期时线程也会被重新调用
3. awaitNanos(long nanosTimeout)
这个方法通过被指定毫微的超时时间,会返回一个线程剩余要等待的毫微时间数。如果超时了的话,该返回值是小于等于0的。
4. awaitUninterruptibly()
该方法是不会产生线程中断情况下的await()方法。
5. awaitUntil(Date deadline)
1 | /** |
6. signal()
唤醒一个等待中的线程。
该线程在从await()返回前,必须重新请求获取锁。
7. signalAll()
唤醒所有的线程。其中每个线程在从await()返回前,都必须重新请求获取锁。