同步异步,阻塞非阻塞(看到的,记录下)打比方很形象,不知是对是错

来源:互联网 发布:ubuntu指定安装路径 编辑:程序博客网 时间:2024/06/05 11:57

假设现在办公室开会,就缺一个人了,在他没有来的时候,大家都在聊天。如果这个人不来,会议就没法召开,这就是阻塞。会议这个线程就被挂起了。这时,我们可以继续聊天这个线程,或者再开一个打牌的线程,但是我们不聊天、打牌,非要等到你来再开会,这是同步阻塞。如果我们边聊天、打牌,边等你来了再开会,这是异步阻塞。
  还是假设现在办公室开会,就缺你一个人了。如果你不来,会议照常可以进行,这就是非阻塞。尽管你不来,会议可以照常进行,这时我们也可以聊天打牌,但是我们没有聊天打牌,非要等你来才开会这就是同步非阻塞,如果你还没有来,我们就开会了,等你来了,再征求你的意见,这就是异步非阻塞,当然在开会的同时我们可能还在聊天或者打牌。
  基于这样的理解,如果是阻塞的话,当前阻塞的线程肯定会被挂起。同步和异步只是针对其他线程而言的,如果其他线程一直再等该线程,那么就是同步阻塞,如果其他线程不等该线程继续或者开始执行,那么就是异步阻塞。
  如果是非阻塞的话,当前线程不会被挂起,只是某个函数调用没有返回,尽管其他线程或者本线程内其他函数可以不等这个函数返回继续执行,但是如果其他线程或本线程的其他函数非要等该函数返回,那么就是同步非阻塞。如果其他线程或者本线程的其他函数没有等该函数返回就继续执行,那么就是异步非阻塞。

 

阻塞就是干不完不准回来,   
非组赛就是你先干,我现看看有其他事没有,完了告诉我一声

我们拿最常用的send和recv两个函数来说吧... 
比如你调用send函数发送一定的Byte,在系统内部send做的工作其实只是把数据传输(Copy)到TCP/IP协议栈的输出缓冲区,它执行成功并不代表数据已经成功的发送出去了,如果TCP/IP协议栈没有足够的可用缓冲区来保存你Copy过来的数据的话...这时候就体现出阻塞和非阻塞的不同之处了:对于阻塞模式的socket send函数将不返回直到系统缓冲区有足够的空间把你要发送的数据Copy过去以后才返回,而对于非阻塞的socket来说send会立即返回WSAEWOULDDBLOCK告诉调用者说:"发送操作被阻塞了!!!你想办法处理吧..." 
对于recv函数,同样道理,该函数的内部工作机制其实是在等待TCP/IP协议栈的接收缓冲区通知它说:嗨,你的数据来了.对于阻塞模式的socket来说如果TCP/IP协议栈的接收缓冲区没有通知一个结果给它它就一直不返回:耗费着系统资源....对于非阻塞模式的socket该函数会马上返回,然后告诉你:WSAEWOULDDBLOCK---"现在没有数据,回头在来看看"

 

同步:阻塞 
异步:非阻塞 
就犹如Windows消息函数SendMessage(同步阻塞)和PostMessage(异步非阻塞)之间的区别一样。

 

同步(NonOverLapped)方式是比较简单的一种方式,编写起来代码的长度要明显少于异步(OverLapped)方式,我开始用同步方式编写了整个子程序,在   Windows98   下工作正常,但后来在   Windows2000下测试,发现接收正常,但一发送数据,程序就会停在那里,原因应该在于同步方式下如果有一个通讯   Api   在操作中,另一个会阻塞直到上一个操作完成,所以当读数据的线程停留在   WaitCommEvent   的时候,WriteFile   就停在那里。我又测试了我手上所有有关串行通讯的例子程序,发现所有使用同步方式的程序在   Windows   2000   下全部工作不正常,对这个问题我一直找不到解决的办法,后来在   Iczelion   站点上发现一篇文章提到   NT   下对串行通讯的处理和   9x   有些不同,根本不要指望在   NT   或   Windows   2000   下用同步方式同时收发数据,我只好又用异步方式把整个通讯子程序重新写了一遍。 
所以对于这个问题的建议是:如果程序只打算工作在   Win9x   下,为了简单起见,可以用同步方式写程序,如果程序打算在   NT   下也可以工作的话,就必须用异步方式写。 

原创粉丝点击