我知道这些注意事项的数百种变化已在网上发布。但是,我还没有找到能够解决我的确切问题的任何东西,因此希望您能帮助我了解情况。
我目前正在使用OpenGL在Java中进行2D游戏开发。使用的语言和图形库与我的问题无关,尽管它具有更一般的特征。
我正在尝试设计一个通用的游戏循环,该循环可以或多或少地用于具有中等沉重图形(主要是位图纹理)甚至可能具有较重游戏逻辑(AI,碰撞检测等)的任何游戏。
基本上,我希望维护一个可以被更新(位置,速度和其他与游戏相关的更新)和渲染(纹理/帧在更新位置)的对象的列表/数组/缓冲区,并且尽可能地流畅和高效。
1)一个线程用于更新+渲染
我尝试并仅使用一个线程(好了,在计算用户输入时为两个)放弃了顺序解决方案。
显然,在交换缓冲区阻塞硬件的同时,浪费了很多好的计算时间,这要求一种更有效的解决方案
2)一个用于更新的线程,一个用于呈现的线程
通过将程序分为更新线程和渲染线程并同步对共享缓冲区的访问,我应该能够确保相当稳定的帧速率。对共享缓冲区的同步访问可以通过多种方式来完成,但是它们都有一个共同点。它们都禁止线程并发。尽管这可能是一个公平的权衡,但我想知道是什么使同步变得必要。
3)与2相同,但没有同步
我确实了解许多由于并发线程的粗心实现而引起的问题。生产者/消费者,读者/作家和类似情况导致潜在的僵局。但是,我不明白,如果满足以下条件(并且应该满足),为什么我需要确保共享数据的同步:
--
所以...我在这里想念什么明显的东西?为什么需要为此设置进行同步?
任何想法,评论或建议都是最欢迎的。或者,如果已经在其他地方解决了这个特定问题,我将为您提供引用。
最佳答案
不同步的方法对您来说很好。如果这是库存的Intel硬件,则加倍。我仍然不会使用它。
不同步的并发几乎永远无法可靠运行的原因是,处理器可以自由分配何时在主RAM和缓存之间进行存储和加载。这可以破坏几乎所有不同步的协议(protocol)。但是,正如您所说,如果您的应用程序中的场景从未发生过突然变化,那么没人会注意到。所有数据都将进入RAM,并且或早或晚对其他线程可见。
但是,您无法保证何时何地,以什么顺序进行操作,这在理论上可能使您以奇怪的方式混合两个后续帧(在场景或其光照的突然改变之前和之后)。
根据您的编程语言及其内存模型(我想C++早于C++ 11?),您可能会发现轻量级同步原语,其保证的副作用是适当的内存障碍,其对性能的影响可以忽略不计。这是我建议的起点。极端的性能优化(超出可以证明的安全范围)应该是优化引擎的最后阶段。
1)i86永远不会重新订购商店。我不认为这在任何地方都有记载,我也不想依赖它。您仍然可以对读取进行重新排序,因此无论如何对您的情况没有帮助。
关于multithreading - 关于渲染循环策略的思考,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11403359/