java - Android 游戏循环中的高级并发

标签 java android multithreading synchronization reentrantlock

我正在尝试同步一对非 UI 线程,一个线程运行游戏逻辑,一个线程渲染,以便以逻辑高效的顺序执行任务。我自己施加的一个约束是整个系统在无分配稳定状态下运行,因此所有显示对象都被返回并“回收”,因此这两个线程必须保持一种双向对话,当我调用'swapBuffers()' 方法。

在伪代码中,游戏线程中的事件顺序如下所示:

while(condition)
{
    processUserInput();
    runGameLogicCycle(set number of times);

    waitForBuffersSwapped();

    unloadRecycleBuffer();  //This function modifies one buffer
    loadDisplayBuffer();    ///This function modifies another buffer

    waitForRenderFinished();

    renderThread.postTask(swapBuffersAndRender);
}

选择渲染线程来执行交换缓冲区的任务,这样游戏逻辑线程就可以同时执行不修改缓冲区的任务。在我的代码中,我结合了交换缓冲区和渲染的任务,并将其定义为一个 Runnable 对象,该对象被发布到渲染线程的处理程序。在伪代码中,可运行的看起来像这样:

{
    //Swap the buffers
}
gameThread.notifyThatBuffersSwapped();
{
    //Render items to screen
}
gameThread.notifyThatItemsRendered();

我的问题是实现问题。我熟悉处理程序、同步块(synchronized block)和 ReentrantLocks 的概念。我知道 Lock.await() Lock.signal() 方法,但是当我试图理解它们在迭代循环中调用时的行为时,我发现文档不够充分。

如何实现 ReentrantLocks 让两个线程以这种方式相互等待?如果可能,请在您的回答中包含一个实用的成语。

最佳答案

我不确定 Lock 是否是您想要的。您确实希望当前线程拥有对对象的独占访问权,但是一旦您释放了锁,您希望确保在您再次获得锁之前另一个线程可以执行。

例如,您可以使用命名不当的 ConditionVariable :

loop:
game thread: does stuff w/objects
game thread: cv1.close()
game thread: cv2.open()
[render thread now "owns" the objects]
game thread: does stuff w/o objects
game thread: cv1.block()
game thread: [blocks]

loop:
render thread: does stuff w/objects
render thread: cv2.close()
render thread: cv1.open()
[game thread now "owns" the objects]
render thread: cv2.block()
render thread: [blocks]

这两个线程同步运行。在对非共享对象执行操作时,您会获得一些并发性,但仅此而已。

java.util.concurrent 提供了 CountDownLatch,但这是一个一次性对象,这违背了您避免分配的愿望。奇特的 CyclicBarrier 做得更多。

这不是一个很好的解决方案——虽然锁不是您想要的,但它们是您想要的一部分,我在这里取消了它们。不可能查看代码并轻松确定两个线程不能同时对对象进行操作。

您可能需要考虑对对象进行双缓冲。您需要两倍的内存,但同步问题更简单:每个线程本质上都有自己的数据集要处理,您唯一需要暂停的时间是游戏线程想要交换数据集时。并发性最大化。如果游戏线程延迟,渲染线程将再次绘制它拥有的内容(如果您使用的是 GLSurfaceView)或跳过渲染。 (你可以花哨地对整个事物进行三重缓冲以提高吞吐量,但这会增加内存使用和延迟。)

关于java - Android 游戏循环中的高级并发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16923337/

相关文章:

java - JAXB 使用不同标签解码 XML 元素

java - 从 HashMap 中删除列表中未列出的字符串

Java:将有符号整数转换为无符号长

python - Flask Web 服务器的多处理与多线程

c - 多线程程序消费者导致程序卡住

java - request.getParameter 不检查 UI 中的复选框...Servlet (J2EE)

android - Dagger 2 : error: [Dagger/MissingBinding] cannot solve this one

Android 退出时清除图像内存缓存

java - 无法在 Fragment Activity 上删除和创建数据

linux - 如何在Linux中控制并行任务以避免过多的上下文切换