1.经典答案
同步和异步关注消息通信机制
同步:发出一个调用,在没有得到结果之前,该调用不返回
异步:调用发出之后,直接返回,不等待结果,被调用者会通过消息、状态来通知调用者或通过回调函数来处理这个调用
阻塞和非阻塞关注程序在等待结果(消息、返回值)时的状态
阻塞:调用结果在返回之前,线程会被挂起,调用线程只有在得到结果时才会返回
非阻塞:不能立刻得到调用结果之前,调用不会挂起线程,而立刻返回
2.个人疑惑
上面的经典答案,仔细一看,还是会给人一些疑惑
同步和阻塞的区别?非阻塞和异步的区别?异步是如何实现?
3.个人理解
要解开上面的疑惑,还要知道阻塞这个概念,
阻塞:表示一个线程的状态---->当线程中调用某个函数,需要IO请求,或者暂时得不到竞争资源的,操作系统会把该线程阻塞起来去执行其他线程,避免浪费CPU资源,等到得到了资源,再变成就绪状态,等待CPU调度运行
同步和阻塞:同步是一个顺序执行的过程,不一定会发生线程调度,阻塞是发生了线程的调度,让出了cpu资源
异步和非阻塞:这2者比较像,但是异步有可能发生线程调度,非阻塞是肯定不发生线程调度
阻塞/非阻塞IO是文件属性,不是函数属性,对于普通文件,read、write是不阻塞的,对于网络文件,read、write是阻塞的
异步实现:执行一个操作后,可以执行一部分后或直接去执行其他操作,等待通知来了之后再来执行剩余的操作,实际在这个过程一般需要自己去捕获状态、通知,例如信号处理函数,或者在某个框架中传入一个函数指针,实现回调,整个过程肯定有某一个线程去检查这个状态
4.扩展延伸
当我们相要获得数据的时候,是用阻塞的方式去读还是不阻塞的方式去读,都是不太理想,例如recvfrom,这个函数可以设置为阻塞还是非阻塞
阻塞:本来我想要cpu去处理当前线程的其他事情,但是因为阻塞,导致线程挂起,有可能其他线程没有什么事情可做,导致cpu时间浪费
不阻塞:本来我们想要cpu去处理其他线程,但是不阻塞,当前线程必须要用完时间片,cpu才会去执行其他线程
上面这2种都会导致cpu时间利用率不高,所以出现了select函数,多路IO复用
while(1)
{
select();阻塞一定时间,处理其他线程任务
当前线程任务;
}
但是select函数还是有弊端的,有一个升级版的函数epoll,这个函数节省了更多cpu时间
参考资料:
https://www.cnblogs.com/George1994/p/6702084.html
https://www.jianshu.com/p/2116fff869b6
https://blog.csdn.net/dinglang_2009/article/details/50461697
https://www.cnblogs.com/Anker/p/3265058.html