您的位置:首页技术文章
文章详情页

java - 同步/异步与阻塞/非阻塞之间的差异具体是什么?

【字号: 日期:2023-11-26 09:05:19浏览:33作者:猪猪

问题描述

就我的理解,同步/阻塞是同一概念,都是客户端等待服务端的回执,服务端不返回回执,客户端就不往下走;而异步/非阻塞则是客户端不等待服务端的回执,直接往下走,等到服务端处理结束后,在调用异步回调函数通知客户端。

但具体的,同步和阻塞,异步和非阻塞间的区别,分不清,有谁能解惑呢?

问题解答

回答1:

推荐一篇博文聊聊Linux 五种IO模型,写的很不错。简要的跟你说下这几个。首先,只有同步才有所谓的阻塞非阻塞,异步并没有。常规的错误理解是,我们觉得异步就是非阻塞的,然而并不是这样的。这里的同步和异步的区别就是,对于一个网络IO或者磁盘IO的“整个过程”有没有存在阻塞,是整个过程。以一次read的系统调用为例子,作为一个用户线程,当你发起一次read的系统调用的时候,可以分为两个操作,

一是数据读取:把数据从磁盘读到内核空间,我们都知道,read属于系统调用,用户级线程是无法操作的,只能交给内核线程去处理,而内核线程首先要找到数据,并读到内核空间中。

二是数据复制:把数据从内核空间读取到用户空间。然后用户线程才可以使用这些数据。

所以简单的说,

同步就是上述两个过程都阻塞了,你用户线程一直在等。

非阻塞就是上述第一个过程你没有阻塞,但是用户线程必须不断的询问os,数据是否从磁盘拷贝到内和空间了,如果拷贝好了,则在数据复制的过程阻塞。所以所有的同步过程,在第二阶段都是阻塞的,尽管这是非阻塞的调用。

多路复用:和非阻塞一样,在第二阶段也是阻塞的,但是第一阶段不再由自己去询问操作系统,而是统一交给一个内核线程去处理(linux上实现的有poll,以及改进版的epoll),当你的数据读取完成,这个线程就发送一个信号给原先发起系统调用的用户线程,然后用户线程就进入阻塞,并开始数据拷贝了。

异步:上述两个过程都是非阻塞的。

上述只是简单描述,希望有帮助

回答2:

同步异步的概念主要是描述IO方面的。简而言之同步和异步的主要区别是通知调用进程或线程的方式,立即返回通知即同步,通过注册回调通知则是异步。阻塞和非阻塞主要描述函数的调用返回情况。函数立即返回即非阻塞,函数被挂起则阻塞。

举个简单类比场景,假如你去餐厅点餐。

同步阻塞

你跟订餐员说要一份台湾牛肉面,订餐员听见之后就去厨房,过了一会才拿出来给你。这段时间你就在前台傻傻的等着,没有任何回复,什么也不做(阻塞),你在下单之后没有收到任何回复,一直等待的过程就是同步的通信。

同步非阻塞

你跟订餐员说要一份兰州牛肉面,订餐员回复你说,估计要五分钟。然后你想了一下,五分钟可以刷一刷帖子,干点别的事情解闷。可是很快肚子饿,你每隔一分钟就问一次好了没,得到的回复就是还没好,直到5分钟后,才拿到面。等待的过程中你没有闲着,可以干别的事情,这是非阻塞。由于你还是主动询问结果并等待订餐员的回复,所以这还是同步的。

异步阻塞与非阻塞

所谓异步,就是不需要你主动去询问结果,而是注册一个回调函数。即你点餐完毕之后,订餐员给了你一个号。旁边有一个机器,轮到你的时候,机器就会叫号。通知你的这个过程叫异步,如果你在一旁坐着,啥也不干,那么你就是阻塞状态。如果在一旁刷网页,那么就是非阻塞。

所以区别同步还是异步,主要在于消息的通知方式,阻塞和非阻塞在于函数调用等待通知时的状态,即是否挂起,以至于当前的线程或者进程,和还是能否继续做别的。

通常还有一种协程式的方式实现异步非阻塞。即函数调用遇到IO的时候,注册回调函数后,就挂起返回,因为返回了,所以是非阻塞,然后等IO完成了,回调函数通知唤醒挂起的函数,此时就是异步。

回答3:

一般来说阻塞和非阻塞式指IO调用是立即返回(非阻塞)还是等待完成再返回(阻塞)。同步和异步是个广义概念,是阻塞和非阻塞的表现。

回答4:

其实你理解的很对,同步就是指不会出现数据的不统一,单线程是顺序执行。不同步就是会出现数据不统一的现象,比如多线程的时候,这个线程用到的数据可能会被另一个线程给改了,就造成数据不同步了。而阻塞和非阻塞是指在线程运行的时候是否等待函数返回,如果是单线程就会一直等待,如果是多线程的就不等待向下执行这个时候就容易出现不同步的情况了。

标签: java
相关文章: