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

2023-03-11 15:42:11 +08:00
 adian

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

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

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

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

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

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

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

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

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

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

gptchat:

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

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

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

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

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

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

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

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

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

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

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

协程( Coroutine ):
协程是一种轻量级的线程,可以在同一个线程内实现多个协程的切换,从而实现并发执行。协程可以提高程序的并发性和响应性,也可以避免多线程中的线程同步和资源竞争问题。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/923159

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX