虛擬執行緒相對於Actor模型或平臺執行緒的主要優勢? - Reddit

banq 發表於 2022-05-05

大多數java伺服器使用具有一定執行緒限制(200、300 ..)的執行緒池,但是你不受作業系統的限制來產生更多,我已經讀過對於linux的特殊配置,你可以達到巨大的數量。
然而,作業系統執行緒更昂貴,啟動/停止速度更慢,必須處理上下文切換(由它們的數量放大),並且您依賴於可能拒絕為您提供更多執行緒的作業系統。
話雖如此,虛擬執行緒也消耗相似數量的記憶體(一篇部落格),因此,也存線上程同步和執行緒上下文複製的問題,那麼虛擬執行緒是如何解決的?

回答:
1、JEP 425回答了您所有的問題,包括您連結到的部落格文章中關於記憶體使用的混淆(這誤解了應用程式中大多數虛擬執行緒的來源和目的)。
簡而言之,你可以擁有比平臺執行緒多幾個數量級的虛擬執行緒,虛擬執行緒不會替換您的應用程式當前使用的平臺執行緒;相反,應用程式中的每個任務都可以產生自己的虛擬執行緒。

那麼,即使在不知道是否存在任何阻塞的情況下,是否建議為事件回撥生成新的虛擬執行緒?
這其實是Actor模型(如果你聽說過Akka,那麼你就聽說過 Actor 模型。)
Loom 是一種在(vanilla)JVM 上實現 Actor 模型的支援技術。
Loom 在組合或併發管理方面並沒有真正新增任何東西。

2、虛擬執行緒不需要消耗類似平臺執行緒的一樣多的記憶體。
對於淺層堆疊(這更常見),虛擬執行緒的效率要高得多,因為它不會分配滿1MB(或你設定的任何東西)。
如果你有類似2000幀的深執行緒,那麼是的,它會使用大量的記憶體,因為真的沒有辦法繞過它。
然而,我認為在現實生活中,我所看到的真正瘋狂的堆疊的唯一程式碼是Rxjava/Project reactor的東西,在大多數情況下,Loom可以取代。

3、上下文切換已經是被虛擬執行緒解決的問題了嗎?
上下文切換並不是由虛擬執行緒 "解決 "的。如果你有100000個由16個平臺執行緒組成的FJ池支援的虛擬執行緒,而且這些虛擬執行緒並沒有對任何東西進行阻塞,那麼只有16個虛擬執行緒在實際做任何事情。剩下的99984個虛擬執行緒則是無限期的卡住。

在100000個本機執行緒中,沒有一個是阻塞的,上下文切換是以時間間隔發生的,以確保所有執行緒都能取得進展。
在100000個執行緒中,CPU花在執行上下文切換上的時間並不比100個本地執行緒的執行時間多。

想象一下,每個執行緒的時間間隔是1ms,而且只有一個CPU核心。無論有多少執行緒在執行,每秒都會有1000次上下文切換。
如果有100000個執行緒,每個執行緒執行1ms,然後暫停近100秒,直到它再次執行。

但是,這與虛擬執行緒的目的完全相反。它們應該被用於爭奪一種不是CPU的資源的時候。在任何時候,大多數虛擬執行緒都應該處於阻塞狀態,即等待IO、訊號或鎖。

對於共享CPU來說,你顯然不能比把任務放在佇列中,讓cores平臺執行緒處理它們更好。這裡有一個權衡:如果你的工作負載有一部分是阻塞和計算的,那麼在一個有多個平臺執行緒的排程器上執行虛擬執行緒是有意義的。

對於正在考慮使用虛擬執行緒的人來說,這是一件重要的事情,他們需要了解。它們不是銀彈,而且在使用不當的情況下可能會導致大問題。

上下文切換的問題並沒有被虛擬執行緒所解決

4、虛擬執行緒目標之一是避免多重同步。
想象一下,您正在編寫一個聊天,您需要在 300-500 個執行緒中擁有 100,000 個上下文。
您只需執行 100,000 個執行緒並編寫最少的程式碼。
這是直觀且易於理解的。
第二種實現這個聊天的方法是反應式的,但難以編寫和除錯。
通過Loom虛擬執行緒,經典編碼方法在新的抽象層次上達到了一個新的層次。