V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
mikej
V2EX  ›  Node.js

NodeJS关于同步式I/O和异步式I/O的一点疑问?

  •  
  •   mikej · 2014-01-23 13:18:12 +08:00 · 5764 次点击
    这是一个创建于 3938 天前的主题,其中的信息可能已经有所发展或是发生改变。
    刚刚踏入NodeJS的世界,对同步式I/O和异步式I/O有点不理解。

    同步式I/O:当线程的执行过程中遇到I/O操作时,通常会很耗时,这时操作系统会剥夺这个线程的cpu使用权,将资源分配给其他的工作线程,当I/O操作完毕时,再恢复其对cpu的控制。照这个意思来说,是不是I/O操作是与cpu无关,I/O完成之后线程再继续执行?

    异步式I/O:当遇到I/O操作时,不会等待I/O操作完成,而只是将 I/O 请求发送给操作系统,继续执行下一条语句。当操作系统完成 I/O 操作时,以事件的形式通知执行 I/O 操作的线程,线程会在特定时候处理这个事件。这里为什么是发送给操作系统,或者说为什么操作系统会有处理I/O的能力?

    先多谢各位了。。
    15 条回复    1970-01-01 08:00:00 +08:00
    judasnow
        1
    judasnow  
       2014-01-23 13:35:00 +08:00
    我推荐这篇文章给你,注意看那个图。
    ----
    大概说一下我自己的理解,nodejs 采用一个 "事件循环(event loop)" 这是一个单独的线程,在nodejs执行的过程中是不会退出的。另外还有很多"工作线程(worker)"。其中"工作线程是按需生成的"其完成之后会返回到“事件循环”中(通过callback)。
    ----
    现在来看你的疑问:
    1 是不是I/O操作是与cpu无关,I/O完成之后线程再继续执行?
    io操作过程中 是几乎不需要 cpu 参与的 (通过dma控制器),对于 io 操作,系统(操作系统)会产生一个中断,并将当前线程调度到阻塞状态。io完成后 会将其加入待执行队列中 等待调度。

    2 这里为什么是发送给操作系统,或者说为什么操作系统会有处理I/O的能力?
    io操作归根到底 是由 操作系统提供的系统调用来提供的。
    ----
    我认为你可以多了解下 计算机组成原理 以及 操作系统 这两门课的相关知识。

    可以在 google 上搜索关键词: 系统调用,进程调度,dma控制器
    judasnow
        2
    judasnow  
       2014-01-23 13:35:18 +08:00   ❤️ 1
    mikej
        3
    mikej  
    OP
       2014-01-23 14:26:25 +08:00
    @judasnow 基本上解决了我的问题,那篇文章也很有用,多谢了。
    MichaelYin
        4
    MichaelYin  
       2014-01-23 16:23:09 +08:00
    不知道楼主是否有其他语言基础,这个问题我以前也不懂,讲解的文章其实我也看过,但是真正用代码实现过后才真正明白两者的不同
    建议你用py的socket,threading模块实现一个简单的服务器到客户端的小应用,把几种方式都写一遍,然后你基本对于同步异步,阻塞非阻塞会有比较深刻的认识,从我经验出发我不认为你看完这篇文章就能理解
    FrankFang128
        5
    FrankFang128  
       2014-01-23 16:42:17 +08:00 via Android
    最好永远不要在node里调用耗时的同步方法。
    zythum
        6
    zythum  
       2014-01-23 17:06:06 +08:00
    打个比方就知道什么是同步什么是异步了

    同步的起床要出门:
    洗澡(20分钟)-> 刷牙(5分钟)-> 喂狗(5分钟)-> 穿衣服(5分钟)-> 找钥匙(40分钟)
    需要(75分钟)

    异步的起床要出门:
    洗澡(20分钟)
    刷牙(5分钟)
    喂狗(5分钟) => 需要(40分钟)
    穿衣服(5分钟)
    找钥匙(40分钟)
    mikej
        7
    mikej  
    OP
       2014-01-23 17:32:26 +08:00
    @MichaelYin 深知!光表面的理解肯定是不够的,必须经过大量的编程实践才能理解。ps:我是做php开发的
    yyfearth
        8
    yyfearth  
       2014-01-23 18:10:06 +08:00
    简单来说,同步执行,主线程必须等待任务一一执行完毕,总的执行时间是单纯的加法
    异步执行,由于任务可以请求发出后不需要等待,多个任务可以重叠执行,所以主线程的执行等待时间减少
    pfitseng
        9
    pfitseng  
       2014-01-23 18:36:51 +08:00 via Android
    @judasnow 看到dma 顺便请教下,在arm 编制kernel 的时候好像没dma 选项,那就是都靠cpu 了?
    judasnow
        10
    judasnow  
       2014-01-23 21:02:07 +08:00
    @pfitseng 不是很了解 arm 哈,你可以 google 一下 :-)不过我觉的 arm 中肯定涉及 dma。 全靠 cpu 效率太低。
    judasnow
        11
    judasnow  
       2014-01-23 21:04:51 +08:00
    另外,看了楼主是做 php 开发的,我觉的楼主可以考虑下 如何在 php 中模拟(注意是模拟)异步操作,可能有更助于理解 nodejs 的运行模型。
    judasnow
        12
    judasnow  
       2014-01-23 21:07:22 +08:00
    mikej
        13
    mikej  
    OP
       2014-01-23 22:33:03 +08:00
    @judasnow 恩啊,多谢,还得慢慢研究啊。
    tonitech
        14
    tonitech  
       2014-01-24 10:11:54 +08:00
    @zythum 这个比喻很好!
    bombless
        15
    bombless  
       2014-01-24 15:23:36 +08:00   ❤️ 1
    这个东西考虑起来实际上挺绕的……
    其实整体来说效果是这样的:不管同步还是异步,你I/O消耗多少时间其实是不变的。而CPU时间它是客观流动的。所以在较抽象的层次也就是nodejs这一层,实际的效果就是,两者的差别在于在I/O完成之前的那些CPU时间可以被异步应用利用掉,但同步的应用无法利用掉这些时间。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5793 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 03:30 · PVG 11:30 · LAX 19:30 · JFK 22:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.