V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
adian
V2EX  ›  程序员

今天一早的搜索,终于对同步、异步、阻塞、非阻塞、中断、轮询、多线程,协程这几个概念有了理解

  •  
  •   adian · 2023-03-11 15:42:11 +08:00 · 3255 次点击
    这是一个创建于 624 天前的主题,其中的信息可能已经有所发展或是发生改变。

    感觉从控制流的角度理解这几个概念是最方便的,控制流就是现在做什么、接下来做什么、再接下来做什么。。。

    当然要精准把握还是要从寄存器上下文、内核态和用户态的角度来看

    • 同步 意思就是只有一个控制流
    • 异步 意思就是至少有两个控制流
    • 阻塞、非阻塞 这个词多出现在 Linux 的 IO 模型中,是专有名词,不能望文生义,一定要了解那几个 IO 模型实际做了什么,也许这里面还有一些历史因素吧,感觉能不用这两个词语就不用这两个词语
    • 中断、轮询 这两个词我在 CPU 相关的文章中经常见到,描述键盘输入打断 CPU 原有的控制流、CPU 周期性的访问某段地址空间,两种方式给 CPU 的压力不一样。看到很多文章说什么“中断是一种硬件轮询,中断是不断的检测某个标志位”,但是我还是觉得两者完全不一样,对 CPU 而言,中断是被动的,轮询是主动的
    • 多线程、协程 前者是系统层面的,后者是语言层面的。之前这里面我有个误区,我一直认定一个线程才能代表一个控制流,协程是一个控制流里的魔法操作,现在不这么想了,之后多写写代码再加深理解

    在 v 站上搜索帖子,有 V 友说协程分为有栈协程和无栈协程(似乎协程和协程还都不太一样),也有 v 友说要了解协程还是先从 EventLoop 看起,我感觉协程和闭包应该有关系,要调度各个控制流就需要保存上下文。

    今天一早的搜索,走过最多的弯路是判断不同人对这些概念的理解,尤其是各式的比喻,目前对这些概念有了一个稳定自洽的印象,接下来写代码看看原理看有没有什么新的理解

    希望这段能给对这些概念比较模糊的 v 友带来点启发,然后对这些概念有更准确理解的前辈还望多赐教

    第 1 条附言  ·  2023-03-28 22:19:21 +08:00
    我之前的理解不对
    14 条回复    2023-03-11 20:43:09 +08:00
    churchmice
        1
    churchmice  
       2023-03-11 16:00:55 +08:00   ❤️ 1
    其实花点时间,好好把 csapp 看一遍,相信我,长此以往对你有帮助
    基础还是要打牢,虽然平常 crub 惯了
    shitx
        2
    shitx  
       2023-03-11 16:08:53 +08:00 via iPhone   ❤️ 1
    单论协程最近看了一些资料确实还有挺多细分,对称和非对称协程,有栈和无栈,coroutine 和 fiber ,1 对 N 和 M 对 N 等等,不过核心确实就是保存上下文,保存的方式大致按照解释器和编译器的实现划分,前者可以利用延续和闭包实现,后者通常是一组汇编指令保存寄存器状态比如 setjmp 这种。推荐这篇文章我觉得挺好: https://graphitemaster.github.io/fibers/
    ugpu
        3
    ugpu  
       2023-03-11 16:17:03 +08:00   ❤️ 1
    没其他意思. 感慨下
    现在这些框架完善 拿来即用 编程门槛降低. 这些都是基础知识了, 或者说一个标准程序员的基础知识.
    roycestevie6761
        4
    roycestevie6761  
       2023-03-11 16:40:46 +08:00   ❤️ 2
    可能你写的代码太高层了,这些概念对于我这种工作学习中几乎用纯 C 的人来说,基本不用刻意理解,因为代码里无时无刻不操作中断、寄存器、内核用户态什么的。

    我觉得搞底层高层需要什么再学什么,不然没多大意义。像你说的寄存器什么的,搞 go java js 的啥时候也用不到的,没必要学我觉得
    gant
        5
    gant  
       2023-03-11 16:45:18 +08:00   ❤️ 1
    我基础知识不高,都是直接上各种框架库。
    TWorldIsNButThis
        6
    TWorldIsNButThis  
       2023-03-11 17:03:59 +08:00   ❤️ 2
    对称非对称现在没啥意义,都是上古的东西了,除非你用 lua 可能会涉及到一些这个内容,反正我不用

    自 C#开创 async 以来实际主流就是两种,一种是无栈,
    实现是编译器魔法+线程池,基本就等价于给线程池( eventloop )喂 task
    c# rust kotlin js python c++ std 都这种,async await 关键字就是给编译器的提示可以把后面的代码编译成给线程池喂 task

    一种是有栈
    也就是运行时把操作系统那套线程数据结构+调度器自己在语言内实现一遍,然后再把调度的结果喂给线程池去执行
    go java c++ boost
    所以不用特别的关键字,只需要用的地方 ofVirtual ( java )或者 go 让运行时用语言内置的线程数据结构+调度器来承接接下来要运行的函数,以及函数内调用的函数。这样不断地递归调用,就形成了一个函数调用栈,这就是有栈协程说的那个栈
    qwq11
        7
    qwq11  
       2023-03-11 17:20:36 +08:00   ❤️ 2
    中断确实是“轮询”,不过是硬件去查询而不是软件。CPU 会在执行几条指令之后检查中断寄存器的状态,如果被设置了中断,会先保存上下文,然后跳到系统中断表里指定位置执行。有些文章说中断不是轮询,是因为不是软件去轮询,硬件操作要高效得多,说简单点 CPU 执行程序的方式也就是 while { exec(*(pc++)); check_interruption(); },也能说成是个“写”了个死循环

    进程、线程、协程都差不多,都是对 CPU 的抽象(相似的,fs 是对磁盘的抽象 etc ) ,只是实现层面不太一样而已,进程和线程都是内核态的玩意,协程是用户态
    encro
        8
    encro  
       2023-03-11 18:03:12 +08:00
    我:请解释一下同步、异步、阻塞、非阻塞、中断、轮询、多线程,协程这几个概念

    gptchat:

    同步:指的是在执行一个操作时,必须等待该操作完成后才能进行下一步操作。在同步模式下,程序的执行顺序是由代码的顺序决定的。

    异步:指的是在执行一个操作时,不需要等待该操作完成,可以同时进行其他操作。在异步模式下,程序的执行顺序不受代码顺序的限制,而是由事件的发生顺序决定的。

    阻塞:指的是在执行一个操作时,如果该操作没有完成,程序会一直等待,直到该操作完成后才能继续执行下一步操作。

    非阻塞:指的是在执行一个操作时,如果该操作没有完成,程序不会等待,而是立即返回,继续执行下一步操作。

    中断:指的是在执行一个操作时,如果发生了某个事件,程序会暂停当前操作,转而去处理事件,处理完事件后再回到原来的操作继续执行。

    轮询:指的是在执行一个操作时,程序会不断地查询某个状态或者事件是否发生,直到状态或事件发生为止。

    多线程:指的是在一个程序中同时执行多个线程,每个线程可以独立执行一个任务,从而提高程序的并发性和效率。

    协程:指的是一种轻量级的线程,可以在一个线程中同时执行多个协程,每个协程可以独立执行一个任务,从而提高程序的并发性和效率。协程的切换是由程序自己控制的,不需要操作系统的干预,因此具有很高的效率。
    encro
        9
    encro  
       2023-03-11 18:04:28 +08:00
    既然提到轮询,你就必须提 push 和 pull ,哈哈
    alexleee
        10
    alexleee  
       2023-03-11 19:17:02 +08:00
    同步,异步要看在哪个层面 ,站在 JVM 层面、框架层面和操作系统层面可能结果都不同
    statumer
        11
    statumer  
       2023-03-11 19:30:03 +08:00   ❤️ 1
    你这只是看了个科普水平,没写过 event loop 和 epoll 是不可能搞明白的。
    ysc3839
        12
    ysc3839  
       2023-03-11 20:15:38 +08:00 via Android
    @TWorldIsNButThis 无栈协程和线程池没有必然联系,本质是可以中途返回的子程序,也可以看成是回调函数的语法糖。C++和 JavaScript 的无栈协程都没有和线程池或 event loop 绑定。Python 是和 event loop 绑定的,不能直接当回调函数用。
    adian
        13
    adian  
    OP
       2023-03-11 20:41:33 +08:00
    @statumer 是的,确实没有写过,这个安排上了。基础真重要
    Dorian101
        14
    Dorian101  
       2023-03-11 20:43:09 +08:00
    同步( Synchronous )和异步( Asynchronous ):
    同步和异步是指程序执行的方式,其中同步指程序按顺序执行,每个任务必须等待前面的任务执行完成后才能执行,而异步则指程序可以在执行一个任务时同时执行另一个任务,不需要等待前一个任务执行完毕。

    阻塞( Blocking )和非阻塞( Non-blocking ):
    阻塞和非阻塞是指程序在等待一个操作完成时的状态,其中阻塞指程序在等待操作完成期间无法执行其他操作,而非阻塞则指程序在等待操作完成的同时可以继续执行其他操作。

    中断( Interrupt )和轮询( Polling ):
    中断和轮询是指程序获取外部事件的方式,其中中断指程序通过注册一个中断处理程序来响应事件,而轮询则指程序周期性地查询事件是否发生。

    多线程( Multithreading ):
    多线程是指在一个进程内同时执行多个线程,每个线程可以独立地执行不同的任务。多线程可以提高程序的并发性和响应性,但也需要考虑线程同步和资源竞争等问题。

    协程( Coroutine ):
    协程是一种轻量级的线程,可以在同一个线程内实现多个协程的切换,从而实现并发执行。协程可以提高程序的并发性和响应性,也可以避免多线程中的线程同步和资源竞争问题。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   920 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 22:07 · PVG 06:07 · LAX 14:07 · JFK 17:07
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.