我知道您已经接受了其他答案,但第三种选择是使用 java.util.concurrent.atomic 包的 AtomicReference 类。这提供了自动执行的检索、更新和比较操作,而无需任何支持代码。所以在你的例子中:
public void render()
{
AtomicReference<MouseBallClass> mouseBall = ...;
// ... rendering various objects
MouseBall tmpBall = mouseBall.get();
if (tmpBall != null) tmpBall.draw();
}
这看起来与 Greg 的解决方案非常相似,从概念上讲,它们的相似之处在于幕后都使用波动性来确保值的新鲜度,并在使用值之前获取临时副本以便应用条件。
因此,此处使用的确切示例对于展示 AtomicReferences 的威力并不是那么好。相反,请考虑您的其他线程仅在它已经为空时才更新鼠标球变量 - 对于各种初始化样式的代码块来说这是一个有用的习惯用法。在这种情况下,通常必须使用同步,以确保如果您检查并发现球是空的,当您尝试设置它时它仍然是空的(否则您会回到原来的问题领域)。但是,使用 AtomicReference 您可以简单地说:
mouseBall.compareAndSet(null, possibleNewBall);
因为这是一个原子操作,所以如果一个线程“看到”该值为 null,它还将在任何其他线程有机会读取它之前将其设置为 possibleNewBall 引用。
另一个使用原子引用的好习惯是,如果您无条件地设置某些内容,但需要对旧值执行某种清理。在这种情况下,您可以说:
MouseBall oldBall = mouseBall.getAndSet(newMouseBall);
// Cleanup code using oldBall
AtomicIntegers 不仅有这些好处;getAndIncrement() 方法非常适合全局共享计数器,因为您可以保证每次调用它都会返回一个不同的值,而不管线程的交错。线程安全,大惊小怪。