<tr id="tp1vn"><td id="tp1vn"><dl id="tp1vn"></dl></td></tr>
  1. <p id="tp1vn"></p>
  2. <sub id="tp1vn"><p id="tp1vn"></p></sub>
    <u id="tp1vn"><rp id="tp1vn"></rp></u>
    <meter id="tp1vn"></meter>
      <wbr id="tp1vn"><sup id="tp1vn"></sup></wbr>
      日韩第一页浮力,欧美a在线,中文字幕无码乱码人妻系列蜜桃 ,国产成人精品三级麻豆,国产男女爽爽爽免费视频,中文字幕国产精品av,两个人日本www免费版,国产v精品成人免费视频71pao
      網易首頁 > 網易號 > 正文 申請入駐

      UE5多線程|FRunnableThread

      0
      分享至


      【USparkle專欄】如果你深懷絕技,愛“搞點研究”,樂于分享也博采眾長,我們期待你的加入,讓智慧的火花碰撞交織,讓知識的傳遞生生不息!

      這是侑虎科技第1908篇文章,感謝作者南京周潤發供稿。歡迎轉發分享,未經作者授權請勿轉載。如果您有任何獨到的見解或者發現也歡迎聯系我們,一起探討。(QQ群:793972859)

      作者主頁:

      https://www.zhihu.com/people/xu-chen-71-65

      UE游戲包與編輯器中都有眾多線程,多線程可以充分利用CPU多核特性,提升游戲表現,而且現代CPU核數越來越多,游戲多線程就更有必要了。

      一、線程類型

      線程可分為專用線程和線程池中線程。

      專用線程為GameThread,RenderThread,StatsThread等,它們各自都干專門的事情,比如GameThread用于驅動游戲邏輯,RenderThread用于渲染,StatsThread用于干性能分析。在事情干完后會進入阻塞狀態,不消耗CPU資源。

      線程池線程包括PoolThread和TaskGraphThread,每個線程用于干多種異步任務。游戲中許多任務并發量大,但持續時間短,比如求解動畫藍圖,每幀都開幾個線程求解,求解完再銷毀線程無疑很浪費。另外有很多瑣碎的多線程任務,單獨為它們開線程也很浪費。因此UE使用了線程池,池中線程會循環利用,不斷執行不同的異步任務,當沒有任務時也處于阻塞狀態。

      使用多線程時,UE已對底層平臺接口進行了封裝,開發者無需關注平臺差異,直接使用UE提供的統一接口即可。

      常用的多線程方式包括:RunnableThread、ThreadPool 和 TaskGraph。這三者在底層線程的實現機制上有所不同,對外提供的接口種類豐富,部分接口還支持通過參數指定所使用的線程實現方式。

      二、FRunnable & FRunnableThread

      基本的線程使用方式為FRunnable與FRunnableThread的組合,用于創建專用線程,比如AsyncLoadingThread與渲染線程等。FRunnable負責邏輯,FRunnableThread負責具體線程,線程承載了邏輯,兩者一一對應,好處是上層邏輯與底層平臺接口分離。

      FRunnable

      FRunnable類本身代表一個抽象的“可運行”對象,只有幾個接口,不涉及線程細節,是我們寫邏輯的地方,理論上可以在任意線程執行。

      接口如下:

      • Init Runnable的初始化,初始化可能成功,可能失敗,失敗會立即返回,線程結束。

      • Run執行邏輯主體,初始化成功后執行。

      • Exit Run中任務執行完后的正常退出接口,執行清理操作。

      • Stop由其他線程調用,用于中途停止該Runnable以及背后的線程,但具體如何停止要我們自己實現。

      • GetSingleThreadInterface,當UE強制單線程模式時,返回用于Tick執行的實例,用的不多。

      上述接口不用我們調用,對應線程創建好后會自動調用。

      示例FAsyncloadingThread:

      該類用于處理異步資源加載,會另開一個線程加載資源,繼承了FRunnable,內部的Thread變量存儲線程。


      Init函數沒做什么,Run函數如下:


      主體是一個while循環,StopTaskCounter是循環退出條件,為Atomic計數器,當未被設置時就不斷處理加載,被設置后即退出。

      Stop函數如下,會設置StopTaskCounter變量:


      創建線程,啟動Run邏輯。

      只需要下面一行代碼即可,詳細會在下文介紹:

      FRunnableThread

      FRunnableThread是平臺線程的抽象,也是基類,與平臺相關的線程操作由多個子類完成,包括:

      • FRunnableThreadWin

      • FRunnableThreadUnix

      • FRunnableThreadApple

      • FRunnableThreadAndroid

      我們不需要繼承和修改這些類,使用即可。

      成員變量:

      • FString ThreadName:線程名。

      • FRunnable* Runnable:對應Runnable。

      • FEvent* ThreadInitSyncEvent:同步的Event。

      • EThreadPriority ThreadPriority:線程優先級,UE自己抽象了幾個枚舉。

      接口:

      • Kill:結束線程,UE建議不要用操作系統的Kill接口,強殺線程會導致泄露和死鎖,應該調用Runnable的Stop方法。

      • WaitForCompletion:忙等,直到線程執行完。

      • Suspend:讓線程掛起或繼續執行。

      • SetThreadPriority:設置線程優先級。

      FRunnableThreadWin

      看下常見的Windows平臺子類如何實現。

      Windows平臺的線程為內核對象,通過HANDLE持有索引,這里的Thread就是底層的線程。


      Kill方法內調用了Runnable的Stop,該函數由我們自己實現,然后可選忙等,最后調用操作系統的CloseHandle方法釋放線程內核對象。


      Windows有TerminateThread方法可以直接結束線程,但平常不推薦調用,有以下幾個原因:

      • 線程函數中C++對象的析構函數不會被執行;

      • 線程棧不會被清理,除非調用TerminateThread的線程結束。這是Windows有意為之,加入其他在運行的線程要引用被“殺死”線程堆棧上的值,就會引起非法內存訪問;

      • DLL通常會在線程終止時收到通知,但TerminateThread會導致DLL收不到通知,從而不執行正常的清理工作。

      Suspend方法調用兩個操作系統接口,掛起和恢復:


      SetThreadPriority方法同樣調用了操作系統接口,只是要做優先級轉換,Windows平臺線程優先級為0-31,31最高。


      Windows中WaitForSingleObject可以實現WaitForCompletion效果:


      三、創建線程

      使用靜態方法Create可創建FRunnableThread和底層線程:


      • InStack為線程棧大小;

      • InThreadPri為線程優先級;

      • InThreadAffinityMask為線程的CPU運行偏好,一般用默認值;

      • InCreateFlags也一般用默認值。

      函數內部首先創建NewThread對象,Windows平臺即FRunnableThreadWin。如果當前設置了強制單線程模式,還可選創建FakeThread,通過Tick驅動執行。


      之后進入CreateInternal函數,調用操作系統接口創建線程。把Runnable屬性設置為傳入的InRunnable,然后把線程相關參數轉化為適配當前操作系統的參數,調用CreateThread Win32API創建線程,線程執行的函數為_ThreadProc。同時注意到CREATE_SUSPENDED參數,線程創建后默認為掛起狀態,執行了后面的ResumeThread,才會讓改線程運行。ThreadInitSyncEvent用于等待線程的Init執行完畢,執行完后調用線程才會繼續。


      _ThreadProc函數先向UE的線程管理類注冊改線程,然后進入FRunnableThreadWin::Run函數,真正開始邏輯,注意這個Run函數和FRunnable的Run毫無關系。

      首先調用Runnable的Inti函數,之后觸發ThreadInitSyncEvent,通知調用線程繼續。然后執行最主要的Runnable->Run,等Run自動結束了,再調用Runnable->Exit做清理。最后返回ExitCode,改線程終止。



      四、使用方式

      Runnable有多種使用方式:

      1. 手動創建FRunnable和FRunnableThread

      可參考前面的FAsyncLoadingThread,適合一個長期任務,而且工作量大。

      2. Async函數

      有時我們只想在其他線程中執行一個短期任務,線程生命周期不長,此時專門創建一個Runnable子類,并手動創建一個Thread有些繁瑣。引擎提供了Async函數,可以只提供我們想要執行的Lambda函數,引擎為我們創建一個Thread,或者從線程池中選擇一個Thread來執行邏輯。

      使用例子:


      第一個參數用于指定線程模式。

      Async函數定義如下:


      第一個參數為線程執行方式,第二個為傳入的函數對象,第三個為執行完的回調。

      線程執行方式Execution有如下幾種取值:

      • TaskGraph:在TaskGraph框架下執行,會在線程池選一個線程,適合短任務。

      • TaskGraphMainThread:與上面類似,但會用主線程。

      • Thread:創建一個新線程執行,適合長任務。

      • ThreadIfForkSate:不知。

      • ThreadPool:在GlobalThreadPool中選一個線程執行。

      • LargeThreadPool:與上面類似,在LargeThreadPool選線程執行,僅Editor下可用。

      這里我們只關注Thread模式,處理分支如下:


      創建了一個TAsyncRunnable對象,把Function和Promise傳入其中,Promise可理解為上面的CompletionCallback,然后通過FRunnableThread::Create接口創建新線程,執行該Runnable。

      TAsyncRunnable是一種特殊類型,它接收一個Function、Promise或Future作為參數。觀察其Run方法:在SetPromise時會執行我們指派的任務。這個FRunnable和FRunnableThread對象是匿名的,外部代碼僅進行New而不Delete,其生命周期由TAsyncRunnable自身托管。具體的清理做法是將刪除操作提交至任務隊列(TaskGraph)。之所以不立即Delete,是因為此時Run函數可能尚未執行完畢,立即Delete自身可能導致異常情況。


      3. AsyncThread函數

      和Async函數類似,內部都用TAsyncRunnable實現,不過它是專門創建匿名線程來執行任務的,因此參數中增加了線程優先級選項,這種用法引擎中不多。


      五、線程同步工具

      多線程環境下線程同步是個問題,UE提供了多種線程同步工具。

      Atomics

      Atomics可以原子的改變一個變量,相比鎖是更輕量的線程同步工具,線程不需要切換狀態,提供更好的性能。從底層視角看,原子操作也是有鎖的,現代多核CPU會通過電路信號鎖Cache的方式來實現原子操作,只是這個過程很快。原子操作是一些多線程安全類型的實現基石。

      使用場景

      常見使用場景為實現多線程安全的計數器,比如SharedPtr里的引用計數,下面的SharedReferenceCount類型就是std::atomic。


      UE引擎提供了幾個類型,是對操作系統和C++ Atomic功能的封裝。

      FPlatformAtomics

      可對一個地址進行原子操作,如Add,Exchange。在不同平臺上會調用各自原子操作接口,Windows為Win32Api的_InterlockedExchange等接口。

      示例


      TAtomic

      類似std::atomic,底層使用FPlatformAtomics實現,提供相似接口。在UE5中,已被標記為DEPRECATED,推薦直接使用std::atomic。

      FThreadSafeCounter

      封裝的線程安全計數器,提供Increment、Decrement等接口,底層同樣使用FPlatformAtomics實現。

      六、鎖

      鎖可以創建一個臨界區,在臨界區內的代碼只允許一個線程執行,其他線程等待。根據臨界區執行時間,以及平臺實現,鎖可能使線程從運行態切換到阻塞態,讓出CPU,這個狀態切換也需要線程從用戶模式切換到內核模式,切換時間大概1000個CPU周期。因此鎖是較重的線程同步工具。

      FCriticalSection

      UE提供了FCriticalSection作為各平臺鎖的封裝。

      Windows平臺底層使用CriticalSection實現,稱為關鍵段,Windows平臺上也有互斥量Mutex,但CriticalSection相比Mutex速度更快。進入臨界區需要調用EnterCriticalSection,其內部會先用原子操作interlocked檢查是否能訪問資源,如果能訪問,就接著運行,這個速度很快。如果不能訪問,通常先Spin忙等一小段時間,若還不能訪問資源,再使用Event內核對象進入阻塞態。當臨界區比較短時,可以避免用戶模式到內核模式的切換。因此Windows平臺會用CriticalSection。

      Linux平臺底層使用pthread_mutex_t實現。

      Windows實現:

      初始化CriticalSection,4000表示未獲取到鎖忙等的CPU周期。


      加鎖


      解鎖


      示例

      通常使用FScopeLock配合FCriticalSection使用,可以通過構造函數與析構函數機制,使作用域內的代碼成為臨界區。


      Event

      Event用于多線程的同步,比如上文介紹的Windows線程創建,主線程在調用CreateThread后,調用ThreadInitSyncEvent->Wait(),等待新線程完成初始化工作,新建線程初始化后執行ThreadInitSyncEvent->Trigger(),通知主線程繼續執行。

      Windows平臺底層使用Event內核對象實現Event。Event有自動重置和手動重置概念,自動重置時,一個線程執行Trigger后,只有一個Wait的線程會被喚醒繼續執行,手動重置時,所有Wait的線程都會被喚醒,后續要手動調用重置函數,才能使Event變為未觸發狀態。通常都使用自動重置。

      FEvent

      UE使用FEvent類型表示一個Event,有Wait、Trigger、Reset等接口。而且Event是內核對象,創建比較昂貴,因此UE使用EventPool來管理這些Event,根據ManualReset分成兩個Pool。

      EventPool接口:


      WindowsRunnableThread中使用方式:


      文末,再次感謝南京周潤發 的分享, 作者主頁:https://www.zhihu.com/people/xu-chen-71-65, 如果您有任何獨到的見解或者發現也歡迎聯系我們,一起探討。(QQ群: 793972859 )。


      近期精彩回顧





      特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。

      Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

      相關推薦
      熱點推薦
      最美的戰袍最差的戰績,央視解說喊話別再迷戀“高端局”

      最美的戰袍最差的戰績,央視解說喊話別再迷戀“高端局”

      網球之家
      2026-05-25 22:52:10
      鄭欽文出局創7大尷尬數據:第四次大滿貫一輪游 暴跌至第117名

      鄭欽文出局創7大尷尬數據:第四次大滿貫一輪游 暴跌至第117名

      醉臥浮生
      2026-05-25 19:06:14
      臺獨大佬突然倒戈!向北京喊話:可以考慮統一,但有個條件!

      臺獨大佬突然倒戈!向北京喊話:可以考慮統一,但有個條件!

      菁菁子衿
      2026-05-25 13:30:46
      華為扔出一顆“核彈”:全新芯片定律“韜定律”橫空出世!

      華為扔出一顆“核彈”:全新芯片定律“韜定律”橫空出世!

      聽心堂
      2026-05-25 10:42:56
      不被欣賞!不被喜愛!不被尊重!有人反向開炮了!

      不被欣賞!不被喜愛!不被尊重!有人反向開炮了!

      柚子說球
      2026-05-25 20:12:06
      夏奇拉自曝分手內幕:這是我人生最黑暗的時刻

      夏奇拉自曝分手內幕:這是我人生最黑暗的時刻

      赴一場山海啊
      2026-05-25 01:20:34
      這美女也太頂了!主教練喝水好啊!得看!

      這美女也太頂了!主教練喝水好啊!得看!

      柚子說球
      2026-05-25 20:11:02
      奧萊報:梅西遭遇肌肉疲勞,他有三周多的時間能用于恢復

      奧萊報:梅西遭遇肌肉疲勞,他有三周多的時間能用于恢復

      懂球帝
      2026-05-25 22:24:07
      在剛剛!CBA官宣第9位主帥下課!接替者是名帥,曾任中國男籃教練

      在剛剛!CBA官宣第9位主帥下課!接替者是名帥,曾任中國男籃教練

      老吳說體育
      2026-05-25 19:07:36
      鄭欽文淚灑發布會:這是一場沉重的失利,考慮從低級別賽事打起

      鄭欽文淚灑發布會:這是一場沉重的失利,考慮從低級別賽事打起

      全景體育V
      2026-05-25 21:39:23
      有50年從業經歷的煤老板坑了博士縣長

      有50年從業經歷的煤老板坑了博士縣長

      深度財線
      2026-05-25 14:32:25
      孫穎莎世界第一不保!1人或要取代,如今距離已經很近了

      孫穎莎世界第一不保!1人或要取代,如今距離已經很近了

      酷侃體壇
      2026-05-25 16:42:37
      最新:烏克蘭連續攻入俄領土兩大重鎮!導彈與戰機協同打擊

      最新:烏克蘭連續攻入俄領土兩大重鎮!導彈與戰機協同打擊

      項鵬飛
      2026-05-25 20:15:26
      兩年減少1.2億張,中國信用卡數量跌回2018年水平,發生了什么?

      兩年減少1.2億張,中國信用卡數量跌回2018年水平,發生了什么?

      風向觀察
      2026-05-25 19:35:10
      博主曝四川稻城亞丁,劃省道為內部路,硬剛后自駕進入,網友炸鍋

      博主曝四川稻城亞丁,劃省道為內部路,硬剛后自駕進入,網友炸鍋

      另子維愛讀史
      2026-05-25 19:19:03
      半導體大利好!13家先進封裝集體漲停,高盛提前埋伏5家低至40億

      半導體大利好!13家先進封裝集體漲停,高盛提前埋伏5家低至40億

      長風價值掘金
      2026-05-25 20:35:03
      金球獎反轉!最大熱門一夜間易主,登貝萊不穩,姆巴佩也難比

      金球獎反轉!最大熱門一夜間易主,登貝萊不穩,姆巴佩也難比

      祥談體育
      2026-05-25 21:14:17
      烏克蘭成功發射兩顆衛星,2027年組建天基衛星網絡

      烏克蘭成功發射兩顆衛星,2027年組建天基衛星網絡

      史政先鋒
      2026-05-25 22:24:49
      “爸爸不接電話,媽媽不讓回家”,昨天杭州暴雨,17歲女孩情緒崩潰獨坐白馬湖橋邊,關鍵時刻,他們沖了出去……

      “爸爸不接電話,媽媽不讓回家”,昨天杭州暴雨,17歲女孩情緒崩潰獨坐白馬湖橋邊,關鍵時刻,他們沖了出去……

      都市快報橙柿互動
      2026-05-25 18:23:51
      逼瘋了!湖州一商業廣場內,一名商戶情緒失控,當眾怒砸自家店鋪

      逼瘋了!湖州一商業廣場內,一名商戶情緒失控,當眾怒砸自家店鋪

      火山詩話
      2026-05-24 17:24:10
      2026-05-26 05:36:49
      侑虎科技UWA incentive-icons
      侑虎科技UWA
      游戲/VR性能優化平臺
      1578文章數 987關注度
      往期回顧 全部

      科技要聞

      華為:沒有先進光刻機也能造出高端芯片

      頭條要聞

      伊朗媒體披露最高領袖就醫情況

      頭條要聞

      伊朗媒體披露最高領袖就醫情況

      體育要聞

      如果不好好守門,他可能早就繼承家業了

      娛樂要聞

      李晨鄭愷跑男停宣:12年元老被邊緣化

      財經要聞

      起底煤礦“暗面”:假整改、假數據

      汽車要聞

      啟境GT7定檔5月29日預售 提供三電機版本

      態度原創

      時尚
      手機
      本地
      房產
      軍事航空

      Bella的戛納之旅,次次“神級”表現

      手機要聞

      iQOO 16再次被確認,規格信息都已清晰,REDMI能招架住嗎?

      本地新聞

      用云錦的方式,打開江蘇南京

      房產要聞

      工抵房騙局!134套房款入私賬!海南這個盤,坑慘買房人!

      軍事要聞

      俄軍出動“榛樹”導彈襲擊烏克蘭

      無障礙瀏覽 進入關懷版 主站蜘蛛池模板: 亚洲有码av| 亚洲欧洲精品a片久久99| 日韩精品卡一卡二卡三卡四| 狼友福利在线| 乱色熟女综合一区二区三区| 蜜桃网站视频在线观看| 深水埗区| 国产日韩欧美不卡在线二区| 艳妇乳肉豪妇荡乳在线播放| 国产福利萌白酱在线观看视频| 国产在线精品一区二区夜色| 中文字幕无码人妻aaa片| 国产极品视频一区二区三区| 欧美日韩a视频| 国产精品久久久国产盗摄| 亚洲中文字幕久久久一区| 国产精品一区二区婷婷| 91精品少妇一区二区三区蜜桃臀| 国产成人AV一区二区三区在线| 日本亚洲成a人片在线观看| 久久久精品| 天堂网亚洲综合在线| 自拍日韩亚洲一区在线| 国产不卡视频一区二区三区| 国产精品精品免费| 亚洲午夜性猛春交xxxx| 婷婷四房综合激情五月在线| 特黄熟妇丰满人妻无码| 亚洲国产成人AⅤ毛片奶水| 亚洲欧美精品suv| 人人干人人爽| 漂亮人妻洗澡被公强啪啪| 日本一区二区三区精品AⅤ| 国产丰满老熟女重口对白| 色8激情欧美成人久久综合电影| wwww性生活| 熟女一区二区中文在线| 成人日韩熟女高清视频一区| 国产精华AV午夜在线| 亚洲国产人在线播放首页| 国产高清A片|