Unreal Engine提供了多种并发机制,从简单的原子操作,到复杂的TaskGraph系统。线程及其同步机制是最基础的,其本身许多内容和C++标准线程库、Pthread等线程库并无二致。本文简单整理下,UE并发中最基础的内容:
- 线程/线程管理器的结构
- 线程的常见操作
- 三种同步机制:原子操作、临界区/读写锁、事件机制。
1.线程

1.1.结构
接口层:
- FRunnable - 可在任何一个线程中运行的对象,调用模式:Init() -> Run() -> Exit()。
- FRunnableThread - 平台对立的线程对象,创建时根据平台创建相应的子类。
- FThreadManager - 线程管理器,所有使用FRunableThread::Create创建的线程,都会添加都该全局管理器。
- FSingleThreadRunnable - 提供Tick接口,对于不支持多线程的系统,可以创建FFakeThread,然后通过主线程中调用FThreadManager::Tick来驱动FakeThread运行的Tick操作。
实现层:
- FRunnableThreadWin - Windows系统下的线程的实现
- FRunnableThreadPThread - pthread的封装,一般Unix/Linux/Mac多线程都是用pthread库实现。
- FFakeThread - 不支持多线程的系统,模拟一个“假”线程。
1.2.常用操作
创建线程:使用
FRunnableThread::Create创建线程并运行
| 1 | class FSimpleThread : public FRunnable | 
线程回调:在创建的线程中运行
Init、Run、Exit。
| 1 | virtual bool Init() override | 
结束线程:跳出
Run操作,等待线程结束(RunnableThread->WaitForCompletion)。
| 1 | // 等待线程结束(WaitForCompletion),线程的Join操作。 | 
获取当前线程ID和名字
| 1 | uint32 CurrentThreadId = FPlatformTLS::GetCurrentThreadId(); | 
遍历当前所有线程对象
| 1 | inline void DumpAllThreads(const char* Log) | 
1.3.完整示例
https://github.com/david-pp/UESnippets/blob/main/SnippetAsync/Private/SimpleThread.h
| 1 | class FSimpleThread : public FRunnable | 
2.同步机制
支持三种类型的同步操作,用于线程之间的同步操作:
- 原子操作
- 临界区/读写锁
- 事件
2.1.Atomic
FPlatformAtomics
平台独立的原子操作,编译器和系统级的原子操作封装。
原子操作:TAtomic -> std::atomic
TAtomic,是Unreal使用模板实现的原子操作封装,功能类似std::atomic,随着C++标准对于并发支持的完善,官方建议使用std::atomic。
| 1 | TAtomic<int> Counter; | 
支持原子操作的计数器:FThreadSafeCounter/FThreadSafeCounter64/FThreadSafeBool
| 1 | FThreadSafeCounter Counter2; | 
2.2.Locking
互斥锁/临界区:FCriticalSection/FScopeLock
FCriticalSection,Windows下使用临界区实现,Pthread用mutex实现。
| 1 | class ThreadSafeArray | 
读写锁:FRWLock/FRWScopeLock
若读操作远高于写操作,建议使用读写锁。
| 1 | class ThreadSafeArray2 | 
2.3.Event

FEvent,是可等待事件的接口,用来线程之间事件的等待和触发。
- 功能类似std::condition_variable
- Windows系统下使用CreateEvent创建,pthread使用pthread_cond_create来创建。
- 作为系统级的资源,为了降低创建和释放的消耗,创建时优先从EventPool中拿出来一个Event对象。
相关类及其用法:
FEvent - 可等待事件接口,支持ManualReset/AutoReset两种模式。
| 1 | inline void Test_Event() | 
FEventRef - 构造时创建一个Event,析构时释放该事件。
| 1 | inline void Test_Event2() | 
FScopeEvent - 构造时创建一个Event,析构时等待该事件,收到该事件,结束并释放事件资源。
| 1 | inline void Test_Event() | 
3.参考源码
HAL(Hardware Abstract Layer),平台抽象层相关实现,跨平台线程、文件系统等操作。比如,线程相关操作位于FPlatformProcess::XXXX、本地线程缓存位于FPlatoformTLS::XXXX等待。
- Engine/Source/Runtime/Core/Public/HAL/Runnable.h
- Engine/Source/Runtime/Core/Public/HAL/RunnableThread.h
- Engine/Source/Runtime/Core/Public/HAL/ThreadManager.h
- Engine/Source/Runtime/Core/Public/HAL/Event.h
