Android:要求从一个线程访问的变量在另一个线程中立即可用

Android: Require variable accessed from one thread to be immediately available in another

我正在开发一款 OpenGL ES 2.0 游戏,运行 遇到了一个我希望很容易解决的问题。

基本上在我的游戏中,我只使用 OpenGL 提供的 2 个线程。那些是:

我会尝试用一个简单的例子来解释:

所以,在我的 UI 线程 上,在我的 onTouchEvent 方法中,我正在做这样的事情 (包括一些伪代码):

@Override
public boolean onTouchEvent(MotionEvent event) {

    actionMask = event.getActionMasked();
    pointerIndex = event.getActionIndex();  
    pointerID = event.getPointerId(pointerIndex);       

    switch (actionMask){

           //Primary pointer down
           case MotionEvent.ACTION_DOWN: { 

                  if (exitIsPressed){
                      renderer.gameIsPaused = false; //User has exited game, so reset this flag
                      Log.v("Tag","gameIsPaused Value is (from UI Thread): "+renderer.gameIsPaused);
                  }
           }
}

然后在我的 渲染线程 上,我像这样使用变量:

@Override
public void onDrawFrame(GL10 gl) {

    Log.v("Tag","gameIsPaused Value is (from Rendering Thread): "+gameIsPaused);

}

所以,'renderer' 是我的 GLSurfaceView,'gameIsPaused' 布尔标志是 GLSurfaceView class 的成员。我只是想从我的 UI 主题更新它。

当我 运行 代码并按下退出按钮时,我 有时 ,得到这个:

gameIsPaused Value is (from UI Thread): False

gameIsPaused Value is (from Rendering Thread): True

这里的代码是简化的,但我希望它能解释问题。我猜这与访问同一个变量的两个线程有​​关,但是,我真的不确定如何解决这个问题。我在这样的设置中搜索此类问题时看到的大多数帖子似乎都集中在渲染和 updating 线程之间的同步,但是,如您所见,我我只使用一个线程来渲染 更新,所以我的问题具体涉及确保变量在对它们执行某些操作后立即可用于渲染线程 UI线程。

我试图将 gameIsPaused 变量标记为易变的,但是,这没有任何区别。

希望有人能解释这是如何工作的,我应该如何避免这个问题以及为什么。

这是因为两个线程运行并行但是不同线程之间的操作顺序不保证,任何线程都可以随时中断制作日志打印看似乱序:

  1. 渲染线程读取 gameIsPaused 变量值 (true)
  2. 渲染线程准备字符串"gameIsPaused Value is (from Rendering Thread): True"
  3. 线程切换
  4. UI 线程将 gameIsPaused 变量设置为 false
  5. UI线程准备字符串"gameIsPaused Value is (from Rendering Thread): False"
  6. UI 线程打印其字符串
  7. 线程切换
  8. 呈现线程打印其字符串

其他可能性:

  1. 渲染线程读取 gameIsPaused 变量值 (true)
  2. 线程切换
  3. UI 线程将 gameIsPaused 变量设置为 false
  4. UI线程准备字符串"gameIsPaused Value is (from Rendering Thread): False"
  5. UI 线程打印其字符串
  6. 线程切换
  7. 渲染线程从寄存器值
  8. 准备字符串"gameIsPaused Value is (from Rendering Thread): True"
  9. 呈现线程打印其字符串

如果你需要在没有渲染线程的情况下同时设置多个变量 运行ning 当这些变量被设置时你需要使用 mutex 来防止在更改变量时从 运行ning 渲染线程。

另一种选择是在 UI 线程中设置单个变量,让渲染线程完成设置多个变量的工作。

第三种选择是准备一个消息对象并使用消息队列将其发送到呈现线程,以便呈现线程将其作为单个操作处理。

任何这些都将确保渲染线程不会看到一些变量更新而一些变量使用旧值的中间状态。