网络IO之同步、异步、阻塞、非阻塞的本质

87 阅读2分钟

背景介绍

众所周知,讲到IO,离不开这四个名词:同步、异步、阻塞、非阻塞。在《Operating System Concepts [9th Edition]》书中描述对这种进程间通信进行了一些描述。
image.png
简单来说,阻塞和非阻塞也可以称之为同步和异步,其行为本质是一样的,都是下面四种操作的组合

  • Blocking send 阻塞发送,直到数据被接收进程读取;
  • NonBlocking send 非阻塞发送,发送以后,可以处理其他事务;
  • Blocking receive 阻塞接收,接收器一直阻塞,直到有数据为止;
  • NonBlocking receive 非阻塞接收,无论有无数据,接收器都可以检索读取;

在我理解看来,**阻塞非阻塞,关注的是否挂起等待消息执行,也就是send方法;同步异步,关注的是请求结果的通知机制,也就是receive方法。**例如方法a执行时,其中有一行是调用了方法b,阻塞是要等b执行完成以后再执行后续的代码块;非阻塞是把b抛给其他线程执行以后,立马执行后续代码块。
按照这个背景知识,我们可以进行下面四种组合:

同步阻塞

【Blocking send】+ 【Blocking receive】,阻塞发送 + 阻塞接收

int response = Rpc_methodB();
// 拿到执行的结果,做特定的操作
print("do specify. response="+response);
// 做其他事情
print("do other things");

同步非阻塞

【NonBlocking send】+ 【Blocking receive】,非阻塞发送 + 阻塞接收
可以参考轮询模式,提交请求以后,轮询读取结果

Futher responseFuther = threadPool. submit(Rpc_methodB());
// 不等待,有无结果都拿取一次
Integer response = responsefuther. getNow();
if(response != null){
	// 拿到执行的结果,做特定的操作
	print("do specify. response="+response);
}
// 做其他事情
print("do other things 1");
// 做其他事情
print("do other things 2");
// 做其他事情
print("do other things 3");
// 方法最后再尝试获取结果
Integer response = responsefuther. get();
if(response != null){
	// 拿到执行的结果,做特定的操作
	print("do specify. response="+response);
}

异步阻塞

【Blocking send】+ 【NonBlocking receive】,阻塞发送 + 非阻塞接收

// 除非是生产消费模式,否则蠢蠢的
Rpc_methodB();
threadPool. submit(()->{
	for(;;){
		// Rpc_methodB方法将结果写到一个共享变量中
		Integer response = getResponseNow();
		if (response != null){
			// 拿到执行的结果,做特定的操作
			print("do specify. response="+response);
		}
	}
});
// 做其他事情
print("do other things");

异步非阻塞

【NonBlocking send】+ 【NonBlocking receive】,非阻塞发送 + 非阻塞接收

threadPool. submit(Rpc_methodB()).listener(r,e -> {
    if(e == null) {
        int response = r;
		// 拿到执行的结果,做特定的操作
        print("do specify. response="+response);
		// 做其他事情
		print("do other things");
     }
})