三、阻塞/非阻塞、同步/异步理解
这里先定义两个方法funcA和funcB,funcA中将调用funcB,以下我们假设funcB中做了一些耗时的IO操作。
public void funcA() { // 调用funcB funcB(); } public void funcB() { // TODO: 2019/1/4 doSth }
先了解一下内核态和用户态。计算机在调用层上划分了用户态、内核态。
我们编写的应用程序即运行在用户态,与内核态相对隔离。当我们的应用程序发起一个IO操作的时候,会通过API系统调用内核态执行内核操作。
我们可以简单理解为:应用程序的线程调用了系统的API接口,从而在内核中执行了另一个线程执行IO操作。
当执行内核调用的时候,应用程序的线程通常会停止执行,这时候进入了“阻塞”状态。进入阻塞状态的线程不能做任何操作,它得等待内核调用完成。
可是线程如何知道内核调用有没有完成呢?
1、线程一直阻塞,等到内核调用返回结果,即“同步”等待结果。 ---- 阻塞同步
2、线程一直阻塞,等待内核调用通知其已就绪,线程再去获取结果即“异步”等待通知。 ---- 阻塞异步
阻塞的方式使得线程在阻塞期间完全不能做其它事情。于是我们希望在内核调用的执行期间,线程可以继续执行以提高利用率,这种状态即“非阻塞”状态。
非阻塞状态下线程可以继续执行:
1、如果你不断地去轮询内核调用的执行结果,那么即“同步”;---- 非阻塞同步
2、如果你去做了别的事,等到内核调用结束,通知线程的时候才继续执行,即“异步。---- 非阻塞异步
总结:
同步、异步是关注于是主动获取结果,还是被动等通知。阻塞、非阻塞是关注于你是否能继续执行。