Dan*_*ker 284
在许多情况下,它们是同一个东西的不同名称,但在某些情况下它们是完全不同的.所以这取决于.术语不是以完全一致的方式应用于整个软件行业.
例如,在经典套接字API中,非阻塞套接字只是立即返回一个特殊的"会阻塞"错误消息,而阻塞套接字则会被阻塞.您必须使用单独的功能,例如select
或poll
找出何时是重试的好时机.
但异步套接字(由Windows套接字支持)或.NET中使用的异步IO模式更方便.您调用一个方法来启动一个操作,框架会在完成后回调您.即使在这里,也存在基本的差异.异步Win32套接字通过传递Window消息将其结果"编组"到特定的GUI线程,而.NET异步IO是自由线程的(您不知道将调用哪个线程回调).
所以他们并不总是意味着同样的事情.为了提炼插座示例,我们可以说:
Nik*_*sov 46
Yve*_*ves 43
同步/异步是描述两个模块之间的关系.
阻塞/非阻塞是描述一个模块的情况.
例如:
模块X:"我".
模块Y:"书店".
X问Y:你有一本名为"c ++ primer"的书吗?
1)阻塞:在Y回答X之前,X一直在那里等待答案.现在X(一个模块)正在阻塞.X和Y是两个线程还是两个进程或一个线程或一个进程?我们不知道.
2)非阻塞:在Y回答X之前,X只是离开那里并做其他事情.X可能每两分钟回来检查一下Y是否完成了它的工作?或者在Y打电话给他之前X不会回来?我们不知道.我们只知道在Y完成工作之前X可以做其他事情.这里X(一个模块)是非阻塞的.X和Y是两个线程还是两个进程或一个进程?我们不知道.但我们确信X和Y不能是一个线程.
3)同步:在Y回答X之前,X一直在那里等待答案.这意味着在Y完成工作之前,X无法继续.现在我们说:X和Y(两个模块)是同步的.X和Y是两个线程还是两个进程或一个线程或一个进程?我们不知道.
4)异步:在Y回答X之前,X离开那里,X可以做其他工作.在Y打电话给他之前,X不会回来.现在我们说:X和Y(两个模块)是异步的.X和Y是两个线程还是两个进程或一个进程?我们不知道.但我们确信X和Y不能是一个线程.
请注意上面的两个粗体句子.为什么2)中的粗体句子包含两个案例而4)中的粗体句子只包含一个案例?这是非阻塞和异步之间差异的关键.
以下是关于非阻塞和同步的典型示例:
// thread X
while (true)
{
msg = recv(Y, NON_BLOCKING_FLAG);
if (msg is not empty)
{
break;
}
sleep(2000); // 2 sec
}
// thread Y
// prepare the book for X
send(X, book);
Run Code Online (Sandbox Code Playgroud)
你可以看到这个设计是非阻塞的(你可以说这个循环的大部分时间都是无意义的,但在CPU的眼中,X正在运行,这意味着X是非阻塞的)而X和Y是同步的,因为X可以继续做任何其他事情(X不能跳出循环),直到它从Y获得书.
通常在这种情况下,使X阻塞更好,因为非阻塞为愚蠢的循环花费了大量资源.但是这个例子很好地帮助你理解这个事实:非阻塞并不意味着异步.
这四个词确实让我们很容易混淆,我们应该记住的是这四个词用于建筑设计.了解如何设计一个好的架构是区分它们的唯一方法.
例如,我们可能会设计这样一种架构:
// Module X = Module X1 + Module X2
// Module X1
while (true)
{
msg = recv(many_other_modules, NON_BLOCKING_FLAG);
if (msg is not null)
{
if (msg == "done")
{
break;
}
// create a thread to process msg
}
sleep(2000); // 2 sec
}
// Module X2
broadcast("I got the book from Y");
// Module Y
// prepare the book for X
send(X, book);
Run Code Online (Sandbox Code Playgroud)
在这里的例子中,我们可以这么说
如果需要,您还可以使用四个单词描述在X1中创建的线程.
更重要的是:我们何时使用同步而不是异步?我们什么时候使用阻止而不是非阻塞?
为什么Nginx不阻塞?为什么Apache阻止?
要做出一个好的选择,您必须分析您的需求并测试不同体系结构的性能.没有这样的架构适合各种需求.
Mac*_*Mac 15
正如您可以从众多不同(通常是相互排斥的)答案中看到的那样,这取决于您的要求.在某些领域,这些术语是同义词.或者他们可能每个都提到两个相似的概念:
在任何一种情况下,目的都是允许程序不被阻止等待缓慢的过程完成 - 程序预期如何响应是唯一真正的区别.哪个术语指的是程序员,程序员,语言,平台或平台.或者术语可以指代完全不同的概念(例如,与线程编程相关的同步/异步的使用).
对不起,但我不相信有一个正确答案是全球真实的.
Ant*_*ony 15
将此问题放在Java 7中的NIO和NIO.2的上下文中,异步IO比非阻塞更先进一步.使用java NIO非阻塞调用,可以通过调用设置所有通道(SocketChannel,ServerSocketChannel,FileChannel等)AbstractSelectableChannel.configureBlocking(false)
.但是,在这些IO调用返回之后,您可能仍需要控制检查,例如是否以及何时再次读/写等
.例如,
while (!isDataEnough()) {
socketchannel.read(inputBuffer);
// do something else and then read again
}
Run Code Online (Sandbox Code Playgroud)
使用java 7中的异步api,可以以更通用的方式创建这些控件.其中一种方法是使用CompletionHandler
.请注意,这两个read
调用都是非阻塞的.
asyncsocket.read(inputBuffer, 60, TimeUnit.SECONDS /* 60 secs for timeout */,
new CompletionHandler<Integer, Object>() {
public void completed(Integer result, Object attachment) {...}
public void failed(Throwable e, Object attachment) {...}
}
}
Run Code Online (Sandbox Code Playgroud)
Bab*_*yan 12
阻塞调用:控制仅在调用完成时返回。
非阻塞调用:控制立即返回。后来操作系统以某种方式通知进程调用已完成。
同步程序:使用阻塞调用的程序。为了在调用期间不冻结,它必须有 2 个或更多线程(这就是为什么它被称为同步 - 线程同步运行)。
异步程序:使用非阻塞调用的程序。它只能有 1 个线程并且仍然保持交互。
同步被定义为同时发生。
异步被定义为不在同一时间发生。
这是造成第一个混乱的原因。同步实际上就是所谓的并行。当异步是顺序的时,请执行此操作,然后执行该操作。
现在,整个问题都涉及到对异步行为进行建模,因为您已经进行了一些操作,而该操作需要其他操作的响应才能开始。因此,这是一个协调问题,您如何知道现在可以开始该操作?
最简单的解决方案称为阻塞。
阻塞是指您仅选择等待另一件事完成并返回响应,然后再继续进行需要的操作。
因此,如果您需要在烤面包上涂黄油,那么您首先需要烤制烤面包。协调他们的方式是,您首先烤掉繁殖的面包,然后不断凝视烤面包机,直到烤面包机爆裂,然后再在上面放黄油。
这是最简单的解决方案,并且效果很好。没有真正的理由不使用它,除非您碰巧还需要做其他不需要与操作协调的事情。例如,洗碗。当您知道这会花费一些时间并且可以在菜盘洗完时将其洗净的时候,为什么还要不停地凝视吐司机的吐司呢?
这就是另外两个分别称为非阻塞和异步的解决方案发挥作用的地方。
非阻塞是指您在等待操作完成时选择执行其他不相关的操作。如果您认为合适,请检查响应的可用性。
因此,与其看着烤面包机使其弹出,不如将其弹出。你去洗一整盘。然后,您可以窥视烤面包机,看看是否已经吐出了烤面包。如果没有,则您去洗另一盘,检查一下各盘之间的烤面包机。当您看到烤面包突然冒出时,您就不再洗碗了,取而代之的是烤面包并继续往上面放黄油。
但是,必须不断检查烤面包会很烦人,想像一下烤面包机在另一个房间里。在两道菜之间,您浪费时间去另一个房间检查吐司。
这是异步的。
异步是指您在等待操作完成时选择执行其他不相关的事情。但是,您无需进行检查,而是将检查工作委派给其他事情,可以是操作本身或观察者,并且可以在响应可用时通知并可能干扰您,以便您可以进行其他操作:需要它。
这是一个奇怪的术语。这没有什么意义,因为所有这些解决方案都是创建相关任务异步协调的方法。这就是为什么我更喜欢将其称为事件。
因此,对于这个,您决定升级您的烤面包机,以便在烤面包完成后发出蜂鸣声。即使您正在洗碗,您也经常在听。听到哔哔声后,您便在记忆中排队,一旦您洗完当前碗碟,便会停下来将黄油涂在烤面包上。或者,您可以选择中断当前菜的清洗,并立即处理烤面包。
如果您听不到蜂鸣声,可以让您的伴侣为您看烤面包机,并在烤面包准备好时告诉您。您的合作伙伴可以自己选择以上三种策略中的任何一种,以协调其观看烤面包机并告诉您准备好的时间。
最后要说的是,很好的理解是,尽管非阻塞和异步(或我更喜欢称其为事件化)确实可以让您在等待时做其他事情,但您却没有。您可以选择不停地循环检查非阻塞呼叫的状态,而无需执行其他任何操作。但是,这通常比阻止更糟(例如,先看烤面包机,然后移开,然后再回到它,直到完成),因此许多非阻止API允许您从其过渡到阻止模式。对于事件,您可以等待空闲直到收到通知。在这种情况下,不利之处在于添加通知很复杂,并且一开始可能代价很高。您必须购买具有蜂鸣功能的新烤面包机,或者说服您的合作伙伴为您代劳。
还有一件事,您需要意识到这三个方面所提供的权衡。一个显然不比其他更好。想想我的例子。如果您的烤面包机是如此之快,您将没有时间洗碗,甚至没有开始洗碗,这就是您的烤面包机的速度。在这种情况下,开始其他事情只是浪费时间和精力。阻止就可以了。同样,如果洗碗需要的时间比烘烤的时间长10倍。您必须问自己,完成工作更重要的是什么?到那时,吐司可能会变得又冷又硬,这不值得,阻塞也可以。或者,您应该在等待时选择更快的操作。显然还有很多,但是我的回答已经很长了,我的观点是,您需要考虑所有这些,以及实现每个对象的复杂性,以确定它们是否值得,以及是否值得。
编辑:
即使已经很长,我也希望它完整,所以我还要再加两点。
1)通常还存在一种称为多路复用的第四种模型。在这种情况下,当您等待一个任务时,又启动了另一个任务,而当您同时等待两个任务时,又启动了一个任务,依此类推,直到所有任务都开始运行,然后您才等待空闲,但是在所有他们。因此,一旦完成任何操作,您就可以继续处理其响应,然后再返回等待其他响应。这被称为多路复用,因为在等待时,您需要一个接一个地检查每个任务,以查看它们是否已完成,直到完成为止。这是对普通非阻塞功能的扩展。
在我们的示例中,这就像启动烤面包机,然后是洗碗机,然后是微波炉,等等。然后等待其中的任何一个。在检查烤面包机是否完成的地方,如果没有,则需要检查洗碗机,如果没有,则要检查微波炉,然后再次检查。
2)即使我认为这是一个很大的错误,但同步经常被用来一次表示一件事。并且一次异步许多事情。因此,您将看到同步阻塞和非阻塞用于表示阻塞和非阻塞。异步阻塞和非阻塞用来表示复用和事件。
我不太了解我们如何到达那里。但是当涉及到IO和计算时,同步和异步通常指的是所谓的非重叠和重叠。也就是说,异步意味着IO和计算是重叠的,也就是同时发生。而同步意味着它们不是,因此顺序发生。对于同步非阻塞,这意味着您不启动其他IO或计算,而只是忙于等待并模拟阻塞调用。我希望人们不再像那样滥用同步和异步。因此,我不鼓励这样做。
归档时间: |
|
查看次数: |
105488 次 |
最近记录: |