15 | Lock和Condition(下):Dubbo如何用管程实现异步转同步?

2019/12/05 posted in  极客-Java并发实战
  • 同步与异步
  • Dubbo 源码分析

Condition 实现了管程模型里面的条件变量。

Java 语言内置的管程里只有一个条件变量,而 Lock&Condition 实现的管程是支持多个条件变量的。

那如何利用两个条件变量快速实现阻塞队列呢?

一个阻塞队列,需要两个条件变量,一个是队列不空(空队列不允许出队),另一个是队列不满(队列已满不允许入队),这个例子我们前面在介绍管程的时候详细说过。

Lock 和 Condition 实现的管程,线程等待和通知需要调用 await()、signal()、signalAll(),它们的语义和 wait()、notify()、notifyAll() 是相同的。

public class BlockedQueue<T>{
  final Lock lock =
    new ReentrantLock();
  // 条件变量:队列不满  
  final Condition notFull =
    lock.newCondition();
  // 条件变量:队列不空  
  final Condition notEmpty =
    lock.newCondition();

  // 入队
  void enq(T x) {
    lock.lock();
    try {
      while (队列已满){
        // 等待队列不满
        notFull.await();
      }  
      // 省略入队操作...
      //入队后,通知可出队
      notEmpty.signal();
    }finally {
      lock.unlock();
    }
  }
  // 出队
  void deq(){
    lock.lock();
    try {
      while (队列已空){
        // 等待队列不空
        notEmpty.await();
      }  
      // 省略出队操作...
      //出队后,通知可入队
      notFull.signal();
    }finally {
      lock.unlock();
    }  
  }
}

同步与异步

同步与异步的区别?
调用方是否需要等待结果,如果需要等待结果,就是同步;如果不需要等待结果,就是异步。

同步,是 Java 代码默认的处理方式。如果你想让你的程序支持异步,可以通过下面两种方式来实现:

  1. 调用方创建一个子线程,在子线程中执行方法调用,这种调用我们称为异步调用;
  2. 方法实现的时候,创建一个新的线程执行主要逻辑,主线程直接 return,这种方法我们一般称为异步方法。

Dubbo 源码分析

在 TCP 协议层面,发送完 RPC 请求后,线程是不会等待 RPC 的响应结果的。其实很简单,一定是有人帮你做了异步转同步的事情。