- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
第 21 章 多进程
第 21 章 多进程
第 21 章 多进程
上⼀章展⽰了续延是如何使运⾏中的程序获知⾃⼰的状态,并且把它保存 来以便之
后重新执⾏的。这⼀章将讨论⼀种计算模型,在这种模型中,计算机运⾏的不是单个
程序,⽽是⼀组独⽴的进程。进程的概念和程序状态这⼀概念相当接近。通过在前⼀
章的宏的基础上再写⼀层宏,我们就可以把多进程的机制融⼊到 Common Lisp 程序
中。
21.1 进程抽象
多进程这种表现形式,可以很⽅便地表⽰并⾏处理多个任务的程序。传统的处理器同
时只能执⾏⼀条指令。我们称多进程能同时处理多件事情,并不是说它通过某种⽅式
克服了硬件的限制,它真正的含义是:它使得我们可以在⼀个新的抽象层⾯上进⾏思
考,在这个层⾯上我们不需要明确地指定计算机在任何给定的时间在做什么。就像虚
拟内存给我们制造了⼀个错觉,似乎计算机的可⽤内存⽐它的物理内存还要⼤,同样
的道理,多进程的概念使得我们可以假设计算机可以⼀次运⾏多个程序。
从传统上说,对进程的研究属于操作系统领域的范畴。但进程抽象带来的进步并不局
限于操作系统。它们在其他实时的应⽤程序和计算机仿真中⼀样能⼤展⾝⼿。
有很多对于多进程的研究,它们的⽬的都是为了避免出现某些特定类型的问题。死锁
是多进程的⼀个经典问题:两个进程同时停下等待另⼀个做某些事情,就像两个⼈都
拒绝在另⼀个⼈之前跨过门槛。另⼀个问题是查询有可能碰到系统中数据不⼀致的状
态 例如,⼀个余额查询正好在系统将资⾦从⼀个账户转移到另⼀个账户时发⽣。这⼀
章只讨论进程抽象本⾝;这⾥展⽰的代码可以⽤来测试避免死锁和不⼀致状态的算
法,但代码本⾝没有对这些问题提供任何保护。
这⼀章中的实现遵循了本书所有程序默默恪守的⼀条准则:尽可能少的扰乱Lisp 。在
本质上来说,程序应该尽可能多的让⾃⼰像是对语⾔的修改,⽽不是⽤语⾔写就的⼀
个独⽴的应⽤程序。使程序与Lisp 协调⼀致可以使得程序更为健壮,好⽐部件配合良
好的机器。这样做也能事半功倍;有时你可以让Lisp 为你代劳数量惊⼈的⼯作。
这⼀章的⽬标是构建⼀个⽀持多进程的的语⾔。我们的策略是通过添加⼀些操作符,
将Lisp 变成这样的语⾔。我们语⾔的基本构成元素如下:
函数 由前⼀章的 =defun 或者 =lambda 宏定义。
进程 由函数调⽤实例化。活动进程的数量和⼀个函数能够实例化的进程
数量都没有限制。每个进程有⼀个优先级,初始值由创建时给出的参数
指定。
等待表达式(Waitexpressions) 等待表达式接受⼀个变量,⼀个测试表达
式和⼀段代码体。如果进程遇到等待表达式,进程将在这⼀点被挂 ,
直到测试表达式返回真。⼀旦进程重新开始执⾏,代码体会被求值,变
量则被绑定到测试表达式的值。测试表达式通常不应该有副作⽤,因为
它被求值的时间和频率没有任何保证。
调度 通过优先级来完成。在所有能够重新开始执⾏的进程中,系统会运
⾏优先级最⾼的进程。
默认进程 在其他进程都不能执⾏时运⾏。它是⼀个 read-eval-print 循
环。
创建和删除 绝⼤多数对象的操作可以即时进⾏。正在运⾏中的进程可以
定义新的函数,实例化或者杀死进程。
续延使得保存 Lisp 程序的状态成为可能。能够同时保存多个状态离实现多进程也不太
远了。有了前⼀章定义的宏做基础,我们只要不到 60 ⾏的代码就可以实现多进程。
21.2 实现
[⽰例代码 21.1] 进程结构 实例化
(defstruct proc pri state wait)
(proclaim (special *procs* *proc*))
(defvar *halt* (gensym))
(defvar *default-proc*
(make-proc :state #(lambda (x)
(format t ~% )
(princ (eval (read)))
(pick-process))))
(defmacro fork (expr pri)
(prog1 ,expr
(push (make-proc
:state #(lambda (,(gensym))
,expr
(pick-process))
:p
文档评论(0)