JAVA里的锁之六Condition

任意一个Java对象都有一级监视器方法,像wait(),notify()等,这些方法需要与synchronized配合使用可以实现等待通知功能。类似的Condition也提供了相应的方法。
Condition作为一个接口,只定义了一些模板方法,实现都在AbstractQueuedSynchronizer的内部类ConditionObject里。下面是Condition里的方法:
JAVA里的锁之六Condition_第1张图片

简要说明

在调用上面的方法之前,需要先获取到Condition关联的锁。

Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();

当调用await()方法后,当前线程会释放锁并等待,而其它线程调用Condition对象的signal()方法,通知当前线程后,当前线程获取到锁后会从await()方法返回。

实现分析

  • 等待队列
    在conditionObject对象里维护着一个FIFO的等待队列,队列中每个节点都包含了一个线程引用,该线程就是在condition对象上等待的线程。
    一个condition包含一个等待队列,condition拥有首节点(firstWaiter)和尾节点(lastWaiter),当线程调用了await()方法后,将会以当前线程构造一个节点加入到队列的尾部。
    JAVA里的锁之六Condition_第2张图片

在Object监视器模式下,一个对象拥有一个同步队列和一个等待队列,而Lock同步器拥有一个同步队列和多个等待队列。
JAVA里的锁之六Condition_第3张图片

等待
当调用了await()方法后,会使用当前线程进入等待队列并释放锁,同时线程状态变为等待状态。当从await()返回时,当前线程一定是获取到了锁。
JAVA里的锁之六Condition_第4张图片

通知
当调用了signal()方法后,只有在当前线程获取了锁之后,会唤醒在等待队列中等待时间最长的节点(首节点),在唤醒节点之前,节点会被移到同步队列并使用LockSupport唤醒节点中的线程。
JAVA里的锁之六Condition_第5张图片

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

使用场景

使用Condition可以实现等待通知模式,一些特殊的等待队列等。

源码分析可以看这篇文章:源码分析:②ReentrantLock之条件锁Condition
参考文章:《Java并发编程的艺术》

你可能感兴趣的:(java)