无尽码路

清凉夏日,您升官了吗?
所谓之异步
at 2023-12-05 10:15:09, by 鹏城奋青

在计算机系统中,CPU和IO设备之间速度不同,CPU完全不需要等一个IO操作结束才继续,因此在IO操作结束后发一个信号,CPU再去执行与此IO操作相关后续即可更加有效利用CPU资源。这种机制带来的福利如示:

// IO完成回调
func read_complete(content) {
     process(content); 
}

// 耗时的IO操作
read_file(read_complete);

// 其它操作
some_other();

在操作系统一层,通过诸如IO完成端口(IO Complete Port)、Select机制……等等,使得调用者注册的回调函数在IO操作结束后得以执行,上示中的read_complete函数即是。read_file可谓异步操作,some_other不必等它完成即可被执行。

早期程序语言中,read_file异步操作这种写法,回调函数被分割到其它地方,代码看起来不直观。

随着程序语言支持匿名函数,写法可以更优雅一点:

// 耗时的IO操作
read_file((content) { 
     process(content);  // IO完成回调
});

// 其它操作
some_other();

在而向对象语言中,可以设计出更具意义的类型:

Future(() {
     // 费时操作
}).then((value) {
     // 结束操作
});

// 或
Promise(() {
     // 费时操作
}).then((value) {
     // 结束操作
});

// 其它操作
some_other();

当以上形式成为共识后,可以对语言进行进一步改进,添加关键字async、await等,让程序更加优雅:

async fn read_file() ->string {
      result;
}

val content = await read_file(); // 遇到await关键字时,程序等待异步函数完成,异步转同步
process(content);  // 处理IO结果

some_other(); 

异步编程主要还是仰赖完成通知机制,在这个机制上设计出Future/Promise类型,async是此类型的包装语法糖,await是此类型的拆包语法糖,同时也转成了同步!