鸚鵡虛擬機器/多執行緒和併發
多執行緒是解釋型語言(如 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(協程的超類)是儲存的直譯器狀態。協程透過在呼叫.yield指令時儲存一個延續,並在下次呼叫協程時呼叫該延續來操作。
鸚鵡中的執行緒目前尚未實現,儘管開發人員正在積極努力。本節中的材料主要是基於鸚鵡設計文件的推測。一旦併發正式實現,所有這些資訊都將更新。 |
在內部,鸚鵡支援多種不同的方法來執行執行緒。幸運的是,所有這些不同的方法都是抽象的,細節對 HLL 程式設計師是隱藏的。鸚鵡的併發系統是模組化的,因此可以在以後將新的多執行緒技術新增到鸚鵡中,HLL 程式設計師將能夠從這些更改和新增中受益,而無需對他們的程式碼進行任何更改。
有四種基本操作可用於建立和管理新執行緒。在鸚鵡中,執行緒都抽象在任務PMC 中。要建立一個新執行緒,首先建立一個新的任務 PMC,然後將其新增到排程程式中。