对于Serversocket.accept()
和 DataInputStream.read()
等
进程/线程要访问的数据是否未准备就绪,进程/线程是否需要等待;
同步,异步:访问数据的方式,同步需要主动读写数据,在读写数据的过程中还是会阻塞;异步只需要I/O操作完成的通知,并不主动读写数据,由操作系统内核完成数据的读写。
阻塞非阻塞是针对某次系统调用而言,而同步异步是针对整个I/O任务而言。当整个I/O任务(不管中间涉及到多少次系统调用),只要有阻塞环节,就是同步。
在阻塞的情况下,一定是同步的,应该你线程都挂起了,只能等了(谁让你调用的是系统提供的阻塞IO函数呢,你没得选)。
而在非阻塞的情况下,根据你定义的“任务”是什么来决定是同步还是异步,这样理解,假设程序目的是写IO,若定义“A任务”=“把写IO的指令”发给操作系统,从这个“任务”的定义上讲写IO是异步的,因为我写了以后就知道任务执行的结果(系统告诉我它收到这个指令了);
但换个角度想,同样是写IO,定义“B任务”=“发送写IO指令给系统,且保证数据成功写完”,这种情况下就需要看你调用的系统io函数了,如果你调用的系统IO函数说“我只帮你写数据,同时我会有个状态表示我写的进度,你自己来查”,那对这个写操作就是同步,而如果你调用的系统函数功能是:“我帮你写数据,并且你告诉我真正写完以后我需要干什么事情(处理器)”(类似于函数回调),那这个情况下就是异步的。我想说的就是在非阻塞的情况下需要考虑你所定义的任务来看是同步还是异步。
进一步考虑我们大部分人的共识:大部分情况下我们会把读写的任务定义为“读IO的任务是保证数据要在用户空间;而写IO需要保证成功写结束”,就这种共识的情况下继续说,除了AIO外,其它都是同步的,因为,AIO帮你把数据从系统空间搬到了用户空间,或者在写成功后异步执行你定义的处理器。
引用网上栗子:
老张爱喝茶,废话不说,煮开水。
出场人物:老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。
1 老张把水壶放到火上,立等水开。(同步阻塞)
老张觉得自己有点傻
2 老张把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)
老张还是觉得自己有点傻,于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出嘀~~~~的噪音。
3 老张把响水壶放到火上,立等水开。(异步阻塞)
老张觉得这样傻等意义不大
4 老张把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非阻塞)
老张觉得自己聪明了。
所谓同步异步,是对烧开水这个行为而言的。
普通水