2011-03-23 38 views
8

最近我一直在想:他們如何在只有一個線程中實現幾個「線程」?如何實現只有一個線程運行的幾個「線程」

我的意思是,他們如何在一個線程中實現幾個並行運行的代碼段?他們如何保存「線程」的狀態,創建中斷並將CPU傳遞給下一個?

我認爲斯卡拉演員實現這一點。但是如何?

這可以回答JVM或C,沒關係。我真的很想學習它的理論。

+1

協程,對吧? – 2011-03-23 09:51:14

回答

1

做到這一點的一種方法是讓用戶代碼中的線程包爲自己的某種定時器中斷註冊自己。每當它收到這樣一箇中斷時,它就會通知內核停止執行自己運行多個不同線程的所有內核線程。對於這些線程中的每一個,定時器中斷代碼都可以檢查這些線程的堆棧,將重要信息(寄存器,堆棧指針,程序計數器等)記錄在輔助位置,然後加載存儲的信息中的另一個線程在該實際線程上運行。然後它可以恢復運行模擬線程的內核線程。通過這種方式,您可以模擬在單個內核線程上運行的多個線程之間的上下文切換。

要實現類似鎖定的功能,您可以在用戶空間中本地記錄所有鎖定信息。只要模擬線程試圖獲取鎖,就可以檢查線程是否可以成功獲取鎖。如果是這樣,你就給它鎖定。否則,您通過交換在該真實線程上運行的模擬線程來模擬上下文切換,然後將該模擬線程標記爲阻塞,直到該鎖再次變爲空閒爲止。這只是一個開始 - 這裏有很多其他的細節(如果其中一個模擬線程試圖執行阻塞I/O操作?你不能阻塞內核線程,因爲這會阻止所有的線程模擬的線程!),但這是主意。

3

您的意思是像Java中的ExecutorService或ScheduledExecutorService中的任務嗎?

這些任務被添加到一個隊列中,並預先完成。當一個人完成另一個開始。如果您有延遲的循環,則可以使用重複的計劃任務。它爲每個迭代完成並允許其他任務運行。

如果你想知道更多的細節,你可能會發現閱讀有趣的代碼。

+0

我在想更公平的東西,像時間切片等.. – 2011-03-23 10:04:25

+0

@Jose Leal,你的意思是像線程?當線程/線程池中的輕量級任務和已經可以共享CPU的線程時,線程中的線程會獲得什麼? – 2011-03-23 10:20:08

2

使用coroutines

+0

我認爲這個問題更多的是關於如何在1個內核線程上實現n個線程的搶先式多線程。 – templatetypedef 2011-03-23 10:14:28

6

我想你混淆了coroutinesgreen threads這裏。

當它們準備好進行時,協同程序放棄了控制,而沒有任何中斷,因此有關中斷的問題在這裏無關緊要。斯卡拉演員被實現爲協程。

綠色線程是由虛擬機實現的用戶模式線程,無需使用本機操作系統功能。顯然,虛擬機可以將任何指令插入正在執行的代碼中,以檢查是否需要切換到另一個線程。

4

對於演員來說,它很簡單,而不是爲每個演員使用一個線程,而是使用相同的線程爲多個演員執行消息。然而,如果一個actor執行一個阻塞調用或一個繁重的計算,則必須使用另一個線程來執行其他actor中的消息。

綠色線程是輕量級線程,可以在VM級別實現。綠色線程總是映射到一個或多個操作系統線程。同步和線程切換由VM在用戶空間中處理,這可以顯着降低開銷。但是,綠色線程有一些缺點,例如IO調用可能導致線程阻塞,然後VM不能「重新使用」另一個綠色線程的OS線程,而必須使用額外的OS線程。

另一種解決方案是使用在Scala編譯器中實現的continuations。然後在保存和恢復本地狀態的JVM字節碼級別處理中斷和恢復執行。不需要VM支持。

相關問題