首页 > 编程 > Python > 正文

用Python生成器实现微线程编程的教程

2020-02-23 00:39:50
字体:
来源:转载
供稿:网友

微线程领域(至少在 Python 中)一直都是 Stackless Python 才能涉及的特殊增强部分。关于 Stackless 的话题以及最近它经历的变化,可能本身就值得开辟一个专栏了。但其中简单的道理就是,在“新的 Stackless”下,延续(continuation)显然是不合时宜的,但微线程还是这个项目 存在的理由。这一点很复杂……

刚开始,我们还是先来回顾一些内容。那么,什么是微线程呢? 微线程基本上可以说是只需要很少的内部资源就可以运行的进程 ― 并且是在 Python 解释器的单个实例中(在公共内存空间中,等等)运行的进程。有了微线程,我们就可能在目前中等性能的 PC 机上运行数以万计的并行进程,还可以每秒钟几十万次地在上下文之间切换。对 fork() 的调用或标准的 OS 线程调用根本不能达到这个程度!甚至所谓的“轻量级”线程库中的线程也比这里提出的微线程“重”好几个数量级。

我在本专栏中介绍的轻便线程的含义与 OS 线程的含义有一点不同。就这点而言,它们与 Stackless 所提供的也不尽相同。在很多方面,轻便线程比大多数变体都简单得多;大多数关于信号、锁定及诸如此类的问题都不存在了。简单性的代价就是,我提出了一种“协作多线程”的形式;我觉得在标准 Python 框架中加入抢占并不可行(至少在非 Stackless 的 Python 2.2 中 — 没有人知道 __future__ 会带来什么)。

轻便线程在某种意义上会令人回想起较早的 Windows 和 MacOS 版本的协作多任务(不过是在单个应用程序中)。然而,在另一种意义上,轻便线程只不过是在程序中表达流的另一种方式;轻便线程所做的一切(至少在原则上)都可以用“真正庞大的 if/elif 块”技术来完成(蛮干的程序员的黔驴之计)。

一种用简单的生成器模拟协同程序的机制。这个机制的核心部分非常简单。 scheduler() 函数中包装了一组生成器对象,这个函数控制将控制流委托给合适的分支的过程。这些协同程序并不是 真正的协同程序,因为它们只控制到 scheduler() 函数和来自该函数的分支。不过出于实用的目的,您可以用非常少的额外代码来完成同样的事情。 scheduler() 就是类似于下面这样的代码:
清单 1. 模拟协同程序的 Scheduler()

def scheduler(gendct, start): global cargo coroutine = start while 1:  (coroutine, cargo) = gendct[coroutine].next()

关于这个包装器要注意的一点是,每个生成器/协同程序都会生成一个包含它的预期分支目标的元组。生成器/协同程序基本上都在 GOTO 目标处退出。为了方便起见,我还让生成器生成了一个标准的 cargo 容器,作为形式化在协同程序之间传送的数据的方法 — 不过您也可以只用已经达成一致的全局变量或回调 setter/getter 函数来传送数据。Raymond Hettinger 撰写了一个 Python 增强倡议(Python Enhancement Proposal,PEP),旨在使传送的数据能被更好地封装;可能今后的 Python 将包括这个倡议。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表