1、阻塞与非阻塞
阻塞与非阻塞是对同一个线程来说的,在某个时刻,线程要么处于阻塞,要么处于非阻塞。
阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态。
阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。
举个通俗的例子:
你打电话问书店老板有没有《分布式系统》这本书,你如果是阻塞式调用,你会一直把自己“挂起”,直到得到这本书有没有的结果,如果是非阻塞式调用,你不管老板有没有告诉你,你自己先一边去玩了, 当然你也要偶尔过几分钟check一下老板有没有返回结果。
在这里阻塞与非阻塞与是否同步异步无关。跟老板通过什么方式回答你结果无关。
2、同步与异步
同步与异步是对应于调用者与被调用者,它们是线程之间的关系,两个线程之间要么是同步的,要么是异步的。
同步和异步关注的是消息通信机制。
同步操作时,调用者需要等待被调用者返回结果,才会进行下一步操作。
而异步则相反,调用者不需要等待被调用者返回调用,即可进行下一步操作,被调用者通常依靠事件、回调等机制来通知调用者结果。
还是上面的例子,
你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果)。
而异步通信机制,书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了(不返回结果)。然后查好了,他会主动打电话给你。在这里老板通过“回电”这种方式来回调。
3、同步与异步调用/线程/通信
1)同步调用与异步调用
在用在调用场景中,无非是对调用结果的不同处理。
同步调用就是调用一但返回,就能知道结果,而异步是返回时不一定知道结果,还得通过其他机制来获知结果,如:
c. 回调函数
2)同步线程与异步线程
同步线程:即两个线程步调要一致,其中一个线程可能要阻塞等待另外一个线程的运行,要相互协商。快的阻塞一下等到慢的步调一致。
异步线程:步调不用一致,各自按各自的步调运行,不受另一个线程的影响。
3)同步通信与异步通信
同步和异步是指:发送方和接收方是否协调步调一致。
同步通信是指:发送方和接收方通过一定机制,实现收发步调协调。 如:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。
异步通信是指:发送方的发送不管接收方的接收状态。 如:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。
阻塞可以是实现同步的一种手段!例如两个东西需要同步,一旦出现不同步情况,我就阻塞快的一方,使双方达到同步。
同步是两个对象之间的关系,而阻塞是一个对象的状态。
4、I/O操作
IO分两阶段(一旦拿到数据后就变成了数据操作,不再是IO):
1.数据准备阶段
2.内核空间复制数据到用户进程缓冲区(用户空间)阶段
在操作系统中,程序运行的空间分为内核空间和用户空间。
应用程序都是运行在用户空间的,所以它们能操作的数据也都在用户空间。
阻塞IO和非阻塞IO的区别在于第一步发起IO请求是否会被阻塞:
IO,如果不阻塞,那么就是非阻塞IO。
同步IO和异步IO的区别就在于第二个步骤是否阻塞:
IO操作再将结果返回给你,那么就是异步IO。
一般来讲: 阻塞IO模型、非阻塞IO模型、IO复用模型(select/poll/epoll)、信号驱动IO模型都属于同步IO,因为阶段2是阻塞的(尽管时间很短)。
5、同步和异步IO 阻塞和非阻塞IO
同步和异步IO的概念:
/O请求后需要等待或者轮询内核I/O操作完成后才能继续执行
/O请求后仍需要继续执行,当内核I/O操作完成后会通知用户线程,或者调用用户线程注册的回调函数
阻塞和非阻塞IO的概念:
阻塞是指I/O操作需要彻底完成后才能返回用户空间
/O操作被调用后立即返回一个状态值,无需等I/O操作彻底完成
6、总结
阻塞、非阻塞:进程/线程要访问的数据是否就绪,进程/线程是否需要等待;
同步、异步:访问数据的方式,同步需要主动读写数据,在读写数据的过程中还是会阻塞;异步只需要I/O操作完成的通知,并不主动读写数据,由操作系统内核完成数据的读写。
对Unix来讲:阻塞式I/O,非阻塞式I/O,I/O复用(select/poll/epoll)都属于同步I/O,因为它们在数据由内核空间复制回进程缓冲区时都是阻塞的。只有异步I/O模型(AIO)是符合异步I/O操作的含义的,即在 1数据准备完成、 2由内核空间拷贝回缓冲区后通知进程,在等待通知的这段时间里可以干别的事。
参考: