一.使用

选择性地唤醒线程。

  1. public class ReentrantLockCondition {
  2. private static Lock lock = new ReentrantLock();
  3. private static Condition conditionA = lock.newCondition();
  4. private static Condition conditionB = lock.newCondition();
  5. public static void awaitA() throws InterruptedException {
  6. lock.lock();
  7. System.out.println("awaitA");
  8. conditionA.await();
  9. System.out.println("awaitA--------");
  10. lock.unlock();
  11. }
  12. public static void awaitB() throws InterruptedException {
  13. lock.lock();
  14. System.out.println("awaitB");
  15. conditionB.await();
  16. System.out.println("awaitB--------");
  17. lock.unlock();
  18. }
  19. public static void signalA() {
  20. lock.lock();
  21. System.out.println("signalA");
  22. conditionA.signalAll();
  23. lock.unlock();
  24. }
  25. public static void signalB() {
  26. lock.lock();
  27. System.out.println("signalB");
  28. conditionB.signalAll();
  29. lock.unlock();
  30. }
  31. public static void main(String[] args) throws InterruptedException {
  32. new Thread(() -> {
  33. try {
  34. awaitA();
  35. } catch (InterruptedException e) {
  36. e.printStackTrace();
  37. }
  38. }, "线程1").start();
  39. new Thread(() -> {
  40. try {
  41. awaitB();
  42. } catch (InterruptedException e) {
  43. e.printStackTrace();
  44. }
  45. }, "线程2").start();
  46. Thread.sleep(1000);
  47. signalA();
  48. }
  49. }
  50. 输出:
  51. awaitA
  52. awaitB
  53. signalA
  54. awaitA--------

二.源码

1.lock.newCondition

  1. final ConditionObject newCondition() {
  2. // AQS的内部类
  3. return new ConditionObject();
  4. }
  5. // 单向的等待队列
  6. public class ConditionObject {
  7. private transient Node firstWaiter;
  8. private transient Node lastWaiter;
  9. }
  10. class Node {
  11. Node nextWaiter;
  12. }

2.await

  1. public final void await() throws InterruptedException {
  2. // 将当前线程包装成Node,尾插入到等待队列中
  3. Node node = addConditionWaiter();
  4. // 释放锁,唤醒同步队列中的下一个节点
  5. int savedState = fullyRelease(node);
  6. int interruptMode = 0;
  7. while (!isOnSyncQueue(node)) {
  8. // 阻塞
  9. LockSupport.park(this);
  10. if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
  11. break;
  12. }
  13. // 尝试获取锁,获取不到锁阻塞
  14. if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
  15. interruptMode = REINTERRUPT;
  16. // 获取到锁
  17. }

3.signal,不会释放锁,unlock释放锁

  1. public final void signal() {
  2. // 当前线程必须持有锁
  3. if (!isHeldExclusively())
  4. throw new IllegalMonitorStateException();
  5. Node first = firstWaiter;
  6. if (first != null)
  7. doSignal(first);
  8. }
  9. private void doSignal(Node first) {
  10. do {
  11. // 将头结点从等待队列中移除
  12. if ( (firstWaiter = first.nextWaiter) == null)
  13. lastWaiter = null;
  14. first.nextWaiter = null;
  15. } while (!transferForSignal(first) &&
  16. (first = firstWaiter) != null);
  17. }
  18. final boolean transferForSignal(Node node) {
  19. //将节点插入同步队列的末尾
  20. Node p = enq(node);
  21. return true;
  22. }

4.signalAll

  1. public final void signalAll() {
  2. if (!isHeldExclusively())
  3. throw new IllegalMonitorStateException();
  4. Node first = firstWaiter;
  5. if (first != null)
  6. doSignalAll(first);
  7. }
  8. // 等待队列的所有节点插入同步队列的末尾
  9. private void doSignalAll(Node first) {
  10. lastWaiter = firstWaiter = null;
  11. do {
  12. Node next = first.nextWaiter;
  13. first.nextWaiter = null;
  14. transferForSignal(first);
  15. first = next;
  16. } while (first != null);
  17. }