跳转到内容

鹦鹉虚拟机/多线程和并发

来自维基教科书,开放书籍,开放世界

多线程需求

[编辑 | 编辑源代码]

多线程是解释型语言(如 Perl 5)在过去遇到一些问题的领域。以 Perl 5 为例,它有一个非常有漏洞且不可靠的线程实现,它不可扩展。

与 Perl 5 相比,Perl 6 在核心语言中包含了高级多线程和并发功能。为了支持 Perl 6 语言的所有这些高级功能,鹦鹉也必须提供相同的功能。

虽然不是技术上的“多线程”,但协程代表了一种简单的并发形式,随着它被主流程序员接受,将找到许多有趣的用途。协程就像子例程,它们使用yield语句而不是return语句。.yield语句导致协程向调用者返回一个值。但是,.yield不会导致协程退出、消失或丢失其当前状态。下次调用者调用协程时,协程将从上次停止的地方继续执行。以下是一个例子

.sub 'MyCoroutine'
  .yield(1)
  .yield(2)
  .return(3)
.end
.sub 'MyCaller'
  $I0 = 'MyCoroutine'()
  say($I0)
  $I0 = 'MyCoroutine'()
  say($I0)
  $I0 = 'MyCoroutine'()
  say($I0)
.return

函数MyCaller的输出将是

1
2
3

协程在需要维护持久状态的地方立即有用,但在多个调用者或多个线程之间协调该状态可能很困难。一个这样的例子是在文件或数据库访问中,协程可以序列化访问并维护有关文件大小和文件某些特征位置的持久状态信息。

协程在其他地方也称为“延续”,甚至在其他地方称为“延续三明治”。

协程参数

[编辑 | 编辑源代码]

协程的参数只在第一次调用协程时传递,或者在执行.return语句后任何时候调用协程时传递。以下是一个例子

.sub 'MyCoroutine'
   .param int a
   .yield(a)
   .yield(a)
   .yield(a)
   .return(a)
.end

.sub 'main' :main
   $I0 = 'MyCoroutine'(1)  # the "call"
   say $I0
   $I0 = 'MyCoroutine'(2)  # "continuation"
   say $I0
   $I0 = 'MyCoroutine'(3)  # "continuation"
   say $I0
   $I0 = 'MyCoroutine'(4)  # "continuation"
   say $I0
.end

这段代码将打印以下结果,即使MyCoroutine函数的参数在每次调用时都会改变

1
1
1 
1

这是因为只有第一次调用MyCoroutine实际上是创建局部参数的函数调用。其他对MyCoroutine的调用只是延续,而不是调用。延续不会创建新的参数变量。

返回和生成

[编辑 | 编辑源代码]

协程中的 return 调用会导致它向调用者返回一个值并像往常一样销毁其当前词法范围。但是,yield 调用将返回一个值而不会销毁当前词法范围。然后生成将允许协程保持其当前状态并下次调用时恢复其执行。

延续和协程 PMC

[编辑 | 编辑源代码]

这就是协程系统核心的所在,协程 PMC。协程 PMC 是一个对象,它存储协程的状态,以便可以连续多次调用它。延续 PMC(协程的超类)是存储的解释器状态。协程通过在调用.yield指令时存储一个延续,并在下次调用协程时调用该延续来操作。

在内部,鹦鹉支持多种不同的方法来执行线程。幸运的是,所有这些不同的方法都是抽象的,细节对 HLL 程序员是隐藏的。鹦鹉的并发系统是模块化的,因此可以在以后将新的多线程技术添加到鹦鹉中,HLL 程序员将能够从这些更改和添加中受益,而无需对他们的代码进行任何更改。

管理线程

[编辑 | 编辑源代码]
调度程序是调度程序 PMC类型的实例。但是,您不会直接使用调度程序 PMC,鹦鹉会为您使用它。

有四种基本操作可用于创建和管理新线程。在鹦鹉中,线程都抽象在任务PMC 中。要创建一个新线程,首先创建一个新的任务 PMC,然后将其添加到调度程序中。


任务和线程 PMC

[编辑 | 编辑源代码]

软件事务内存

[编辑 | 编辑源代码]



上一个 鹦鹉虚拟机 下一个
Parrot_Magic_Cookies 异常处理
华夏公益教科书