1

为了游戏编程的目的,我正在尝试在一对 Android 线程之间强制同步。我分配了一个处理大部分任务的游戏线程和一个负责交换缓冲区和渲染的渲染线程。当我第一次询问线程同步时,我将 ConditionVariable 对象称为强制线程阻塞直到并发任务完成的有用工具。

我的源代码如下所示:

            ...
            final ConditionVariable bufferLock = new ConditionVariable();
            final ConditionVariable cycleLock = new ConditionVariable();

            bufferLock.open();
            cycleLock.open();

            Runnable bufferSwapTask = new Runnable()
            {
                public void run()
                {
                    swapBuffers();
                    bufferLock.open();
                }
            };

            Runnable renderTask = new Runnable()
            {
                public void run()
                {
                    Log.d(TAG, "drawAll");
                    drawAll();
                    cycleLock.open();
                }
            };

            while(!halt)
            {
                if(!init)
                {
                    synchronized (userInputLock)
                    {
                        fetchUserInput();
                    }

                    processUserInput();
                    gameLogic();

                    bufferLock.block();
                    cycleLock.close();
                    renderThreadHandler.post(renderTask);
                    recycleDisplayObjects();
                    enqueueDisplayTree();

                    cycleLock.block();
                    bufferLock.close();
                    renderThreadHandler.post(bufferSwapTask);
                }
            }
            ...

所以事情以正确的顺序执行,但没有达到我预期的性能水平。而且,当我激活 DDMS 方法跟踪时,我发现 DVM 实际上会中断并阻塞每个线程以允许另一个线程恢复,以强烈暗示两个线程仅由一个 CPU 处理的方式来回切换。

我使用 ReentrantLocks 得到了很好的同时处理结果,那么为什么 ConditionVariable 会有这种效果呢?

4

1 回答 1

2

Android 上的 Linux 内核试图避免在内核之间移动线程。如果一个线程“可运行”(即可以运行但正在另一个线程上等待)一段时间,内核可以决定将它迁移到另一个内核。

如果在以前的实现中,您的一个线程倾向于连续运行,它可能使另一个线程保持“可运行”足够长的时间以使内核迁移它。新的实施可能会以较小的步骤进行并低于阈值。

FWIW,其他人对此感到困惑,例如herehere

于 2013-06-04T22:56:38.613 回答