异步实际上是如何在引擎盖下工作的?

时间:2014-04-10 14:33:06

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

我一直在以同步和异步的方式研究很多多线程,回调,调度队列...... 我的研究越多,我越是感到困惑和沮丧,我觉得我似乎无法理解它......有人可以引导我向正确的方向开始..大多数到目前为止我发现的信息都是关于什么是做什么和有利的东西..我真正希望知道的是,当与回调异步并且在一个线程上时,函数如何立即返回 。 [这里]的(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中的调度队列时,认为队列是指向块或函数的指针的正数数组是正确的,并且线程负责在应用程序中管理此队列。?

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

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

4 个答案:

答案 0 :(得分:3)

在相当多的异步环境中,你只有一个线程可以解决问题。让我们称之为前景'。通过某种调度程序安排了可以处理的东西。函数指针的队列可能形成该调度程序的内容。函数指针与回调几乎相同。

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

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

答案 1 :(得分:3)

这完全取决于我的朋友的实施,如果他们遵循语言规范,每个浏览器都可以做任何他们想要的事情。

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

JavaScript不是一种“线程”语言,它与事件循环流一起工作,在该事件循环流中触发事件,之后触发连续函数,直到没有其他函数可以调用。这就是为什么如果您正在编写“好”代码,很难在JavaScript中阻止UI。

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

关于它是如何工作的一个很好的例子,以及事件循环和经典线程之间的差异,是node.js,我给你举个例子:

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

异步意味着:你告诉一些服务(DOM,服务器等)来执行一个动作,你附加一个事件处理程序,一旦服务告诉你,我会得到你想要的,或者我做了你需要的。并且执行该处理程序时执行任何其他鼠标点击或按键操作。事件处理程序的链接可能是PAINFULL,但我相信它比阻止UI更好。

我希望你觉得这很有用,而不是更加混乱。

答案 2 :(得分:1)

这个答案可能会有点晚,但我也想知道如何实现异步函数(在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

答案 3 :(得分:0)

这里有一些很好的答案。

通过使用事件循环不断监视套接字,我发现了有关ansyc例程如何工作的大量文章。本文还讨论了操作系统的优化,这说明了为什么使用事件循环比使用阻塞线程要便宜。

这里是内容:How does non-blocking IO work under the hood