【问题标题】:how does asynchronous actually work under the hood..?异步实际上如何在幕后工作..?
【发布时间】:2014-04-10 14:33:05
【问题描述】:

我一直在研究很多多线程、回调、调度队列,以同步和异步的方式...... 我研究得越多,我就越困惑和沮丧,以至于我觉得我似乎永远无法理解它。请有人可以引导我找到正确的开始方向。大多数到目前为止,我发现的信息都是关于做什么和优势的东西。我真正想知道的是,当与回调异步并在一个线程上时,函数如何立即返回。 [这里]'s(http://nathansjslessons.appspot.com/lesson?id=1085) 我从哪里得到这些信息的

The function **returns immediately** before the file is read and schedules the read to happen       
sometime in the future. Once the data is ready, the callback function is called on the    
data.

这是一个如何使用常规阻塞读取函数来获取文件内容的示例 var readFile = function() {

var data;
data = read('file.txt');
dosomething('contect' + data);
}

这是使用异步 readAsync 函数的相同示例。

var readFileAsynch = function () {
     var func = function (x) {
          // i can do something with data
         dosomthing('content'+data);
     }
     **readAsynch('file.txt',func);** 
      dosomemorestuff();
     };

据我所知,如果您使用主线程以外的另一个线程而不是我认为的异步方式,那么如果您只有 一个线程(如 javascript),那么异步将如何真正起作用..?

而且,当谈到目标 c 中的调度队列时,是否认为队列只是指向块或函数的指针数组,并且线程负责在应用程序中管理此队列..?

我真的很抱歉我的问题很模糊,但我也是.. 希望任何人都可以提供一些我可以阅读的源代码或实现,以了解真正发生的事情。我厌倦了仅仅阅读诸如“使用线程非常昂贵”之类的东西……但是以什么方式……?或者,我不需要知道它..?

edit:那么 readAsynch('file.txt',func); 与其他函数的行为有何不同,因此它被称为 asynch..?以及为什么它可以立即执行 dosomemorestuff 而无需等待上面的 readAsynch 函数,除非(我认为)当您调用 readAsynch 时,它是由另一个线程完成的..?

【问题讨论】:

  • Javascript 是单线程的,但您的浏览器不是。您的浏览器使用另一个线程等待来自服务器的响应,然后在收到响应时中断您的 javascript 线程,以便处理任何回调。
  • @thefourtheye 我不太确定我是否使用了不恰当的词。我所说的实现的意思是,如果有一个函数充当异步函数,以便我可以调用它,那么无需等待它,执行下一条语句。那么这种函数如何实现异步行为..?

标签: javascript multithreading asynchronous operating-system objective-c-blocks


【解决方案1】:

在相当多的异步环境中,您只有一个线程在处理一些事情。让我们称其为“前景”。通过某种调度程序来安排正在处理的工作。一个函数指针队列可能构成了该调度程序的核心。函数指针与回调几乎相同。

当前台想要做一些耗时的事情时,例如查询数据库或读取文件,然后前台向底层操作系统或库发出请求,并在完成耗时的事情时留下一个回调函数。 (该处理在另一个线程中进行,可能在另一个进程中,或者在内核中,这是非常异步的。)请求具有与之关联的某种 ID,因此当任务完成时,正确的回调得到以正确的结果调用。

当该请求正在进行时,前台可以继续执行接下来的任何操作。如果一个块执行完成,前台将返回调度程序。调度程序将从队列中选择下一个任务。其中一项任务是运行一些回调函数,传入正确的数据,以完成一些缓慢的操作。

【讨论】:

    【解决方案2】:

    这完全取决于我的朋友的实现,每个浏览器只要遵循语言规范,就可以在底层做任何他们想做的事情。

    您不必担心线程和所有这些东西,但如果您这样做,请记住这一点:

    JavaScript 不是一种“线程”语言,它与事件循环流一起工作,在该循环流中触发一个事件,然后触发连续的函数,直到没有更多的调用。这就是为什么在编写“好”代码时很难在 JavaScript 中阻止 UI 的原因。

    可以同时调用多个函数,完全不阻塞,这就是它的美妙之处。函数的每次执行都有自己的生命周期,如果同时触发 3 个事件处理程序,则 3 个事件处理程序将同时运行,而不是线性执行。

    node.js 是一个很好的例子,说明它是如何工作的,以及事件循环和经典线程之间的区别,我会给你一个例子:

    假设您正在服务器上侦听一个请求,并且在请求到达 2 秒后您将发送一条消息。现在让我们假设你复制了那个监听器,两个监听器都做同样的事情。如果您请求服务器,您将在发出请求后 2 秒同时收到两条消息,而不是在 2 秒后收到一条消息,在 4 秒后收到另一条消息。这意味着两个侦听器同时运行,而不是像大多数系统那样遵循线性执行。

    异步意味着:你告诉某个服务(DOM、服务器等)执行一个动作,并且你附加一个事件处理程序,一旦服务告诉你,我已经得到你想要的,或者我'已经做了你需要的。并且该处理程序在执行任何其他鼠标单击或按键时执行。事件处理程序的链接可能很痛苦,但我相信它比阻塞 UI 更好。

    我希望你觉得这很有用,而不是更令人困惑。

    【讨论】:

    • 在您的回答中(异步意味着:您告诉某个服务(DOM、服务器等)执行一个操作,并附加一个事件处理程序,该处理程序将在服务告诉您后执行—— ----------),当我告诉一些服务时,我假设我调用了一些告诉这些服务的函数,然后在我调用这个函数之后,我不必等待这个完成或得到任何回报.. 除非它是由另一个线程完成的..?
    • 这取决于实现,它是如何完成的,但你不应该关心哪个线程运行它,以及是否另一个线程运行它。 JavaScript 不是线程的,它与事件流一起工作,我真的不能告诉你它是否被线程模拟。
    【解决方案3】:

    这个答案可能来得有点晚,但我也想知道如何实现异步函数(在 Node.js 中)以及异步函数如何在提供的回调执行之前立即返回。

    我发现this page about the Event Loop and process.nextTick() 有助于理解它在 Node.js 中的工作原理。

    这个例子取自那里:

    let bar;
    
    function someAsyncApiCall(callback) {
      process.nextTick(callback);
    }
    
    someAsyncApiCall(() => {
      console.log('bar', bar); // 1
    });
    
    bar = 1;
    

    它表明,通过将回调放在process.nextTick() 中,脚本会运行到完成,允许在调用回调之前初始化所有变量、函数等。

    这是我的另一个例子:

    // defining an asynchronous function
    var async_function = function(callback){
        console.log("Executing code inside the async function");
        process.nextTick(function(){
          console.log("Executing code in callback provided to process.nextTick() inside async function");
    
          const startCallback = Date.now();
          while (Date.now() - startCallback < 2000) {
            // do nothing
          }
          callback();
        });
    };
    
    console.log("Code executed prior to calling the async function");
    // calling the async function
    async_function(function() {
        console.log("Executing the callback function provided to async function");
    });
    console.log("Code executed after calling the async function");
    
    // Output:
    
    // Code executed prior to calling the async function
    // Executing code inside the async function
    // Code executed after calling the async function
    // Executing code in callback provided to process.nextTick() inside async function
    // (pause of 2 seconds)
    // Executing the callback function provided to async function
    

    【讨论】:

      【解决方案4】:

      这里有一些很好的答案。

      我找到了一篇关于 ansyc 例程如何通过使用事件循环来持续监控套接字的精彩文章。这篇文章还讨论了 O/S 优化,这解释了为什么使用事件循环比使用阻塞线程更便宜。

      这是写的:How does non-blocking IO work under the hood

      【讨论】:

        猜你喜欢
        • 2018-03-17
        • 2015-05-18
        • 1970-01-01
        • 2016-01-18
        • 2014-02-21
        • 1970-01-01
        • 2018-07-31
        • 1970-01-01
        • 2013-10-04
        相关资源
        最近更新 更多