跳轉到內容

鸚鵡虛擬機器/多執行緒和併發

來自華夏公益教科書,開放書籍,開放世界

多執行緒需求

[編輯 | 編輯原始碼]

多執行緒是解釋型語言(如 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 異常處理
華夏公益教科書