传递多线程数据的最佳设计实践?

Best Design Practices for Passing Around Multithread Data?

我正在尝试创建一个干净高效的设计,用于将事件传递给后台线程进行评估,然后 return 将选定的结果传递给游戏线程。

这是我的初步设计

//Occurrence object passed from director on game thread to background thread OccurrenceQueue

    //Execute BackgroundThread::EvaluateQueues()

        //If OccurrenceQueue.Dequeue()

            //Score Occurrence, then return via Occurrence.GetOwner()->PurposeSelected(Occurrence)

            //EvaluateQueues()

这导致了从一个事件中选择一系列目的的干净循环。所以现在我想把它移到后台线程。这是我到目前为止学到的东西:

根据我上面的了解,我目前的设计在逻辑上似乎是不可能的。

到目前为止,这些是我的替代方案:

我犹豫要不要实施任何利用 tick 来检查数据是否 updated/returned 来自后台线程的设计。

任何人都可以建议相关的设计实践,或者阐明 return 从后台线程执行到主线程的性质(我很难找到 research/info 的正确问题关于这个)?

早上好,

线程可以帮助您完成工作 faster/more 响应迅速但有很​​多陷阱。在这种情况下的简短回答我使用这些结构

#include <future>
#include <thread>
#include <vector> 

int main()
{
     // make data shared
     auto data = std::make_shared<std::vector<int>>();
     data -> push_back(42);

     // future will be a future<int> deduced from return from vector
     // async will run lambda in other thread
     // capture data by value! It copies the shared_ptr and will
     // increase its reference count.
     auto future = std::async(std::launch::async, [data]
     {
        auto value = data[0];
        return value;
        // shared_ptr data goes out of scope and reference count to data is decreased
     });

     // synchronize with thread and get "calculated" value
     auto my_value = future.get();
    // now data on the main thread goes out of scope reference count is decreased. Only when both the thread are done AND this function exits then data is deleted.
    return 0;
} 
  • 大多数对象都会占用内存,并且在分配期间内存不会在 1 个时钟周期内更新。您可以使用 sdt::mutex 和 std::scoped_lock 来保护内存。尝试寻找那些。
  • 你经常需要在线程之间同步information/processing,看看std::condition_variable(但是他们有坑https://www.modernescpp.com/index.php/c-core-guidelines-be-aware-of-the-traps-of-condition-variables
  • C++ 对 类、std::thread 和 std::async/std::future 有很好的支持。我个人喜欢 std::future 的解决方案,因为你可以 return 值和异常 (!) 当您调用 future.get()
  • 时来自其他线程
  • 了解 lambda 和捕获,它们对于与 std::thread/std::async
  • 一起使用至关重要
  • 对象的生命周期!在线程之间共享对象时,您必须确保一个线程不会删除其他线程正在使用的对象。使用线程时不要使用原始指针 and/or new/delete。我个人经常在线程之间共享信息时使用 std::make_shared/std::shared_ptr 到 data/objects。
  • 另一个棘手的事情是,有时您无法确定另一个线程中的工作在创建后是否已经开始。例如。当 std::async returns 一个线程被创建但它不能保证真正开始(操作系统调度等...)。如果您想真正确定它已经启动,那么在异步调用 returns 之后,您将不得不等待您在线程函数开始时设置的 condition_variable。

我希望这些评论可以帮助您入门。

我找到了一个完美的解决方案。由于这些事件对时间不是特别敏感,我只是使用 Unreal Engine 的 AsyncTask() 从我的后台线程在游戏线程上安排一个异步任务。正如@Pepjin Kramer 指出的那样,与 std::async.

相同

这么简单,基本就是一记耳光