开了一个新坑,在看UE的多线程,发现在UE5/Source/Runtime/Core/HAL/Allocators/ThreadSafeBool.h下有:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // DEPRECATED. Please use `std::atomic<bool>` ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
燧重新看起STL的并发库
Threads
std::thread
FString hello(TEXT("hello"));
int pastValue=114514;
std::thread testThread([=](FString s,int pastValue)
{
UE_LOG(LogTemp,Warning,TEXT("%s%d"),*s,pastValue);
},hello,std::ref(pastValue));
std::stringstream out;
out<<testThread.get_id();
FString sThreadId(out.str().c_str());
UE_LOG(LogTemp,Warning,TEXT("the Thread is is:%s"),*sThreadId);
if (testThread.joinable())
{
testThread.join();
}
LogTemp: Display: Hello World
LogTemp: Warning: the Thread is is:57668
LogTemp: Warning: hello114514
std::thread并不一定代表一个线程实例,当调用
template< class F, class... Args >
explicit thread( F&& f, Args&&... args );
构造时,才代表创建一个线程实例,观察std::thread的构造函数发现,它不支持拷贝构造,也不支持拷贝复制,显然一个线程实例仅能被一个std::thread对象代表
about join, detach 和传入参数
因为线程实例在床架完成后立即执行,所以join/detach仅仅对线程的生命周期进行控制, 确保主线程结束是子线程结束,join阻塞主线程指导子线程结束
显然当子线程结束时或thread不代表一个线程实例时,std::thread::joinable返回false;
显然,std::thread需要手动调用join同步主线程和子线程,很麻烦,c++20提供了一个在析构函数join的std::jthread,符合RAII的思想
std::jthread jthread([&](){ int r=0; for (int i = 0; i < 1000; ++i) {r++;} std::cout<<r<<'\n'; }); std::cout<<"main"<<'\n';
Futures
在需要异步执行程序时,往往需要接收异步执行的信息,这需要子线程传递参数给其他线程,stl中为这一操作提供了一系列工具
std::future<std::string> future=std::async([&](){
for (int i = 0; i < 10; i++){
std::cout<<"process: "<<i<<'\n';
std::this_thread::sleep_for(std::chrono::milliseconds(10l));
}
return "success"s;
});
future.wait();
std::cout<<"hello"<<'\n';
auto ret=future.get();
std::cout<<ret<<'\n';
std::async&std::future
创建一个线程,返回一个future对象在调用.get()函数是阻塞主线程等待线程执行完成,获得线程返回值
std::future提供了一个提前阻塞等待线程完成wait();
也可以选择等待一段时间,检查是否运行完成
同样还有wait_until()等待到一个time_point
while (true){
if (auto stat=future.wait_for(std::chrono::milliseconds(200l));stat!=std::future_status::ready){
std::cout<<"waiting\n";
}else{
std::cout<<"finish\n";
break;
}
}
在std::async中第一个参数可以传入std::launch::deferred来决定子线程只在get()被调用时才执行,这不是狭义上的多线程,满足函数式编程的范式,可以用于惰性求值
std::future<std::string> future=std::async(std::launch::deferred,[&](){
for (int i = 0; i < 10; i++){
std::cout<<"process: "<<i<<'\n';
std::this_thread::sleep_for(std::chrono::milliseconds(100l));
}
return "success"s;
});
std::cout<<"hello"<<'\n';
auto ret=future.get();
std::cout<<ret<<'\n';
std::promise
std::future的底层实现与此相关,当需要自己创建线程时,可以引用获取std::promise调用set_value方法,之后调用get_future()方法获取future对象
std::promise<std::string> promise;
std::jthread thread([&](){
for (int i = 0; i < 10; i++){
std::cout<<"process: "<<i<<'\n';
std::this_thread::sleep_for(std::chrono::milliseconds(100l));
}
promise.set_value("success"s);
});
std::cout<<"hello"<<'\n';
auto future=promise.get_future();
auto ret=future.get();
std::cout<<ret<<'\n';
future库还提供了异常处理
评论区