我正在制作一些多线程视频游戏代码。在我开始编码之前,我看了一篇文章,模糊地描述了Valve的多线程游戏设计解决方案。我从文章中收集的一个关键概念是线程同步。我不知道这是Valve怎么做的,但我想象每个执行游戏循环的多个线程。在每次迭代结束时,线程暂停并等待其他线程完成其当前迭代,然后同步共享数据。我认为除了开销是这个管理方案之外,让线程完全异步操作也没有什么不同。文章提到了一个专门用于同步的线程,但我试图让一个不同的解决方案正常工作。这就是我(尝试)这样做的方式:
// at end of loop on each thread...
sig_thread_done();
while (!is_sync_done())
{
PauseExecution(1);
}
sig_thread_done和is_sync_done是来自控制所有“线程”列表的另一个类的函数对象。这些函数如下所示:
bool Core::IsFrameDone()
{
MutexLock lock(manager_mutex);
if (waiting_components == -1)
{
waiting_components = 0;
return true;
}
return false;
}
void Core::SignalFrameDone()
{
MutexLock lock(manager_mutex);
if (++waiting_components == (int)components.size()) // components == threads
{
//sync shared data...
waiting_components = -1; // -1 signifies that all threads have completed their iteration
}
}
问题是快速线程可以退出其等待循环并在其他线程有机会退出之前再次返回它。所以其他线程错过了通过is_sync_done退出,在另一个线程开始等待之前返回false并且整个系统卡住了等待。
我找不到解决此问题的简单方法。我非常喜欢这种方法,因为当某些独立线程执行同步时,同步不会停止。
我感谢任何人提供的任何见解或建议。
答案 0 :(得分:0)
我认为你正试图重新发明Thread barrier。
答案 1 :(得分:0)
对于类似这样的东西你想要在屏障上同步,比如Win32事件(或其数组),这可以确保你无法得到你描述的情况(屏障确保一切同步到达< em> frame )同时释放CPU时间,因为等待事件作为内核信号完成,并且休眠线程直到接收到该信号。你还可以在那里使用无等待算法,如果你有一个基于作业/任务的线程模型,那么这些算法特别好用,其中某些东西可以与系统分离。
此外,here是一个关于多线程源引擎的更好的出版物,它更深入和更具技术性(它们还特别声明它们可以避免这类事物的互斥)。