我熟悉 Java 中围绕并发的许多机制和习语。我感到困惑的是一个简单的概念:同一对象的不同成员的并发访问。
我有一组可以由两个线程访问的变量,在这种情况下涉及游戏引擎中的图形信息。我需要能够在一个线程中修改对象的位置并在另一个线程中读取它。解决这个问题的标准方法是编写以下代码:
private int xpos;
private object xposAccess;
public int getXpos() {
int result;
synchronized (xposAccess) {
result = xpos;
}
return result;
}
public void setXpos(int xpos) {
synchronized (xposAccess) {
this.xpos = xpos;
}
}
但是,我正在编写一个实时游戏引擎,而不是 20 个问题的应用程序。我需要快速工作,尤其是当我像访问和修改图形资产的位置一样频繁地访问和修改它们时。我想删除同步开销。更好的是,我想完全删除函数调用开销。
private int xpos;
private int bufxpos;
...
public void finalize()
{
bufxpos = xpos;
...
}
使用锁,我可以让线程互相等待,然后在对象未被访问或修改时调用 finalize()。在这个快速缓冲步骤之后,两个线程都可以自由地作用于对象,一个修改/访问 xpos,一个访问 bufxpos。
我已经使用类似的方法取得了成功,其中信息被复制到第二个对象中,并且每个线程都作用于一个单独的对象。然而,在上面的代码中,两个成员仍然是同一个对象的一部分,当我的两个线程同时访问该对象时,一些有趣的事情开始发生,即使对不同的成员进行操作也是如此。不可预测的行为、幻影图形对象、屏幕位置的随机错误等。为了验证这确实是一个并发问题,我在一个线程中运行了两个线程的代码,它完美地执行。
我希望性能高于一切,我正在考虑将关键数据缓冲到单独的对象中。我的错误是由对相同对象的并发访问引起的吗?有没有更好的并发解决方案?
编辑:如果你怀疑我对业绩的评价,我应该给你更多的背景信息。我的引擎是为 Android 编写的,我用它来绘制成百上千的图形资源。我有一个可以工作的单线程解决方案,但是自从实施多线程解决方案以来,我看到性能几乎翻了一番,尽管存在幻像并发问题和偶尔的未捕获异常。
编辑:感谢关于多线程性能的精彩讨论。最后,我能够通过在工作线程处于休眠状态时缓冲数据来解决问题,然后允许它们在对象中各自拥有自己的数据集进行操作。