我是gevent的新手。我已经阅读了gevent
的介绍他们提供了简单的示例,但我很难理解 greenlet 是什么。来自学习并发。
Greenlets are a very lightweight coroutine written in C that
are cooperatively scheduled. They provide us with a very lightweight thread-
like object that allows us to achieve concurrent execution within our Python
programs without incurring the cost of spinning up multiple threads.
Greenlet 不是线程? 同步点是如何定义的?有人可以举例说明吗?
同步编程一次只能做一件事。因此,当数据库查询正在运行时,其他人(例如通过 Web 框架拉取网页)必须等待其完成。
Gevent 通过使用上下文切换和事件使其异步。这是什么意思?这样想吧。你有一个队列,里面有等待事情发生的东西,同时 gevent 说,好吧,你可以等待,我将转到下一个任务,并在等待你完成的同时开始做事情(比如数据库读取,或者等待用于用户输入),当您完成后,当我返回队列并且您说您已准备好进行下一步时,我会为您专注于此。
通过这种方式,虽然仍然是单线程,但应用程序可以在作业之间超快速地切换,不断检查状态以查看它是否值得关注,同时,其他事情可以在等待您时完成。
与由操作系统处理且繁重的多线程相反,它们需要自己的资源并且在之间切换的成本很高。
Gevent 可以轻松地将通常使用线程的内容转换为 greenlet。
greenlet 是 CPython C 堆栈上的连续帧块,可以交换到堆中。
这是实现协程所需的一般基本构建块。
Python 中的原生协程实现不会将 C 帧保存到堆中。它被设计为 C 堆栈上没有重要数据,然后在挂起/恢复协程时使用
send()
和 yield [from]
展开/重建 C 堆栈的每个帧。这样做的缺点是,您需要在整个代码库中不必要地发送 yield from
的垃圾邮件链,并承受堆栈展开/重建的所有开销。总体而言,原生 Python 生成器在性能和语法支持方面相当薄弱。
Stackless python 避免使用 C 堆栈 来进行 Python 函数调用(因为如果没有有用的上下文,那还有什么意义呢?)。所有需要的上下文都存储在Python框架中(其中有Python堆栈、IP、本地变量、返回框架等)。 PyPy 包含 Stackless Python,这是它的性能如此出色的部分原因。
Greenlets 的灵感来自 Stackless python。作为 CPython 的扩展模块,C 堆栈仍然用于 Python 函数调用,但您可以按需将帧块(该块“是”协程/greenlet)交换到堆。现在,您可以根据需要混合执行协程来实现目标。这样你就可以得到比 CPython 中的生成器更好的东西,而不必完全切换到 PyPy。