0%

同步(synchronous)/异步(asynchronous)调用和阻塞(blocking)/非阻塞(non-blocking)调用

前言

本文主要介绍同步(synchronous)/异步(asynchronous)调用和阻塞(blocking)/非阻塞(non-blocking)调用的概念以及在现实中会出现的组合场景。

同步(synchronous)/异步(asynchronous)调用

进程/线程在执行过程中,产生一个外部调用,若需要等待该调用返回才能继续往下执行,则称之为同步调用;若不需要等待该调用返回,就可以继续往下执行,则称之为异步调用

阻塞(blocking)/非阻塞(non-blocking)调用

进程/线程在执行过程中,产生一个外部调用,若该调用导致当前进程/线程阻塞,则称之为阻塞调用,否则称之为非阻塞调用。

阻塞:源自操作系统对进程/线程状态的描述概念,其定义为:操作系统把进程/线程从“运行(running)状态”挂起为“阻塞(blocked)状态”(又称“等待(waiting)状态”)。当进程/线程处于阻塞状态,则意味着其处于暂停运行状态,暂时不会被CPU调度执行。

注意:在操作系统领域,“阻塞(blocked)”和“等待(waiting)”的语义相同,但是在其他领域,比如JVM,二者的语义是不一样的。另外,在理解“阻塞”和“非阻塞”时,不能简单地从其字面意思来理解,而是从操作系统对其的基本定义来理解

Q:进程/线程什么时候会发生阻塞?

A:进程/线程主动调用 wait()sleep() 等挂起自己的操作, 或者调用 System Call操作(System Call 因为涉及到了 I/O 操作, 不能立即完成)

PS:此处参考自《怎样理解阻塞非阻塞与同步异步的区别? - 萧萧的回答》

同步(synchronous)/异步(asynchronous)和阻塞(blocking)/非阻塞(non-blocking)的组合

在进程/线程在执行过程中,产生一个外部调用时,有时候会产生同步(synchronous)/异步(asynchronous)和阻塞(blocking)/非阻塞(non-blocking)的组合场景。

异步进程/线程调用

常见情况下,当这个外部调用是一个外部进程/线程调用时,最容易出现以下组合场景:

  • 同步阻塞调用:当前进程/线程在等待调用返回,被调用方进程/线程处于阻塞状态

    如在JS中使用async/await机制,调用方同步调用一个读取磁盘文件的异步线程

  • 同步非阻塞调用:当前进程/线程在等待调用返回,被调用方进程/线程处于非阻塞状态

    如在JS中使用async/await机制,调用方同步调用一个计算哈希值的异步线程

  • 异步阻塞调用:当前进程/线程不等待调用返回,被调用方进程/线程处于阻塞状态

    如调用方异步调用一个读取磁盘文件的异步线程

  • 异步非阻塞调用:当前进程/线程不等待调用返回,被调用方进程/线程处于非阻塞状态

    如调用方异步调用一个发送http请求的异步线程

挂起操作调用和System Call操作调用

  • 挂起操作调用:是指会导致当前进程/线程挂起的调用,如wait()sleep()

  • System Call操作调用:是指系统级别的调用,如中断类函数

常见情况下,当这个外部调用是一个外部进程/线程调用时,最容易出现以下组合场景:

  • 同步阻塞调用:当前进程/线程在等待调用返回,并且处于阻塞状态

    如调用方调用sleep(5)

参考资料: